2012-03-18 2 views
3

С моим английским языком плохо, но я попытаюсь объяснить. У меня вопрос. В JPanel я рисую линию .... они должны выйти за пределы объекта JPanel, а JScrollPane теоретически должен отображать всю панель, но она не обновляется и не отображает все строки, которые были выпущены для области действия панель.JPanel & JScrollPane и рендеринг ошибок

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.Console; 

import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 

public class TestFrame extends JFrame { 

    static int speed = 10; 
    static int floor = 22; 
    public static void createGUI() { 
     JFrame frame = new JFrame("Test frame"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     final Font font = new Font("Verdana", Font.PLAIN, 25); 

     JPanel butPanel = new JPanel();  

     JButton biginButton = new JButton("start"); 
     biginButton.setFont(font); 
     biginButton.setFocusable(false); 
     butPanel.add(biginButton); 

     JButton remButton = new JButton("repaint"); 
     remButton.setFont(font); 
     remButton.setFocusable(false); 
     butPanel.add(remButton); 

     final JPanel labPanel = new JPanel(); 
     final JScrollPane scrollPane = new JScrollPane(labPanel); 
     labPanel.setLayout(new BoxLayout(labPanel, BoxLayout.Y_AXIS)); 

     biginButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       //labPanel.getGraphics().drawString("Ololo", 50, 50); 
       int floH = 100; 
       for(int i = 0; i < floor; i++){ 
        labPanel.getGraphics().drawLine(0, i*floH, 300, i*floH); 
        labPanel.getGraphics().setColor(Color.RED); 
        scrollPane.revalidate();  
       } 
      } 
     }); 

     remButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        labPanel.repaint(); 
        scrollPane.revalidate();         
      }   
     }); 

     frame.getContentPane().setLayout(new BorderLayout()); 
     frame.getContentPane().add(butPanel, BorderLayout.NORTH); 
     frame.getContentPane().add(scrollPane, BorderLayout.CENTER); 

     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     frame.setPreferredSize(new Dimension(screenSize.width-10, screenSize.height-10)); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame.setDefaultLookAndFeelDecorated(true); 
       createGUI(); 
      } 
     }); 
    } 
} 
+0

Что собственно вопрос тогда? – aretai

+0

Что нужно сделать для рисования, увеличенного для прокрутки, если объекты панели за пределами –

+0

'public class TestFrame extends JFrame {' Изменить это на 'public class TestFrame {' & class должен работать точно также (или плохо), поскольку он в настоящее время. –

ответ

5

Я предполагаю, что вы пытаетесь сделать в JPanel, а затем ожидать, что JPanel должен получить больше, чтобы вместить ваш рисунок, и не только это не работает для вас , но вы теряете рисунок, если вы вызываете repaint() на JPanel.

Если это так, то,

  • Просто потому, что вы рисуете за размером JPanel или других JComponent не будет автоматически сделать этот компонент больше, так как сам компонент не имеет «знание», что вы рисуете за его границ. Если вы хотите изменить размер компонента, вам нужно сделать это самостоятельно.
  • Лучше всего, чтобы JPanel установил свой собственный размер, переопределив его метод getPreferredSize(). Это предотвратит возврат другого кода к другому.
  • Вы не хотите получать графику компонента, вызывая на нем getGraphics(). Полученный таким образом графический объект недолговечен, и все, что нарисовано, исчезнет, ​​как только в следующий раз вызывается краска (...) или paintComponent(). Это нормально, чтобы вызвать getGraphics() в BufferedImage, но не на компоненте или JComponent (если у вас нет оснований для этого и не знаю, как защитить объект Graphics, который будет null).
  • Заменить JPanel или какой-либо другой JComponent и нарисовать в методе переопределения paintComponent(...) этого компонента. Если вы используете BufferedImage, тогда вы рисуете BufferedImage в этом методе paintComponent.

Например:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.image.BufferedImage; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class TestDrawing extends JPanel { 
    private static final int PREF_W = 800; 
    private static final int PREF_H = 600; 
    private DrawingPanel drawingPanel = new DrawingPanel(); 

    public TestDrawing() { 
     JPanel northPanel = new JPanel(); 
     northPanel.add(new JButton(new AbstractAction("Draw Lines") { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      drawingPanel.drawLines(); 
      drawingPanel.repaint(); 
     } 
     })); 

     setLayout(new BorderLayout()); 
     add(new JScrollPane(drawingPanel)); 
     add(northPanel, BorderLayout.PAGE_START); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private static void createAndShowGui() { 
     TestDrawing mainPanel = new TestDrawing(); 

     JFrame frame = new JFrame("TestDrawing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class DrawingPanel extends JPanel { 
    private static final int BI_W = 500; 
    private static final int FLOOR = 22; 
    private static final int FLO_H = 100; 
    private BufferedImage img = new BufferedImage(BI_W, FLO_H * FLOOR, BufferedImage.TYPE_INT_ARGB); 

    public DrawingPanel() { 

    } 

    public void drawLines() { 

     Graphics g = img.getGraphics(); 
     g.setColor(Color.black); 
     for (int i = 0; i < FLOOR; i++) { 
     g.drawLine(0, i * FLO_H, 300, i * FLO_H); 
     g.setColor(Color.RED); 
     } 
     g.dispose(); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(BI_W, FLO_H * FLOOR); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (img != null) { 
     g.drawImage(img, 0, 0, this); 
     } 
    } 
} 
+0

Ох. Это именно то, что мне нужно. Большое спасибо. –

+0

Добро пожаловать! –

1

Обращаясь к этой линии:

labPanel.getGraphics().drawLine(0, i*floH, 300, i*floH); 

Рисование линий с использованием графики не рисовать за границы графического объекта. Это означает, что линии фактически не выходят за пределы размера панели. Перед рисованием линий вам необходимо изменить размер панели. Смотрите, если это работает:

int newWidth = Math.max(labPane.getWidth(),300); 
int newHeight = Math.max(labPane.getHeight(),i*floH); 
labPane.setPreferredSize(newWidth,newHeight); 

labPanel.getGraphics().drawLine(0, i*floH, 300, i*floH); 
+2

Пожалуйста, не поощряйте использование вызова getGraphics() 'на компоненте для получения объекта Graphics для рисования. Этот объект является непродолжительным, и все, что нарисовано, исчезнет, ​​как только в следующий раз вызывается 'paint (...)' или 'paintComponent()'. Это нормально, чтобы вызвать 'getGraphics()' на BufferedImage, но не на Компонент или JComponent (если у вас нет оснований для этого и не знаю, как защитить объект Graphics, который будет null). –

+0

В общем, суть куска - лифт. Линии нарисованы - полы. Будет нарисован рядом с самим лифтом (прямоугольник). Все это будет работать на потоках, но я думаю, что там, где рисование фигур и как сделать нормальный путь, если полы на панели не вместе. В конце концов, когда лифт будет двигаться и выходит за панель, ему придется перерисовать его.Или, может быть, лучше перерисовать, как только он переместится на другой этаж? И нужно ли работать с графикой для перехода в другой класс? –

+0

@sombik: любые неподвижные фоновые изображения должны быть нарисованы на BufferedImage, который затем отображается в методе paintComponent JPanel. Движущиеся части изображения могут быть нарисованы непосредственно одним и тем же способом. –

Смежные вопросы