2016-04-02 5 views
0

Я новичок в Java и только начал изучать компоненты графического интерфейса. Итак, я читал Headfirst Java и есть этот код, объясняющий метод paintcomponentJPanel. Это просто изменить цвет овала, когда пользователь нажимает кнопку «изменить цвета». -метод repaint() в JFrame или Jpanel?

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class SimpleGui3C implements ActionListener { 

    JFrame frame; 

    public static void main(String[] args) { 
     SimpleGui3C gui = new SimpleGui3C(); 
     gui.go(); 
    } 

    public void go() { 
     frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JButton button = new JButton("Change colors"); 
     button.addActionListener(this); 

     MyDrawPanel drawPanel = new MyDrawPanel(); 

     frame.getContentPane().add(BorderLayout.SOUTH, button); 
     frame.getContentPane().add(BorderLayout.CENTER, drawPanel); 
     frame.setSize(500,500); 
     frame.setVisible(true); 
    } 

    public void actionPerformed(ActionEvent event) { 
     frame.repaint(); 
    } 
} 

MyDrawPanel Class -

import javax.swing.*; 
import java.awt.*; 

class MyDrawPanel extends JPanel { 

    public void paintComponent(Graphics g) { 

     Graphics2D g2d = (Graphics2D) g; 

//  GradientPaint gradient = new GradientPaint(70,70,Color.blue,150,150,Color.orange); 

     int red = (int) (Math.random() * 255); 
     int green = (int) (Math.random() * 255); 
     int blue = (int) (Math.random() * 255); 
     Color startColor = new Color(red, green, blue); 

     red = (int) (Math.random() * 255); 
     green = (int) (Math.random() * 255); 
     blue = (int) (Math.random() * 255); 
     Color endColor = new Color(red, green, blue); 

     GradientPaint gradient = new GradientPaint(70,70,startColor,150,150,endColor); 

     g2d.setPaint(gradient); 
     g2d.fillOval(70,70,100,100); 
    } 
} 

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

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

Теперь я создал MyDrawPanel класс, расширив JPanel и переопределив его метод paintComponent. Теперь, когда мы помещаем drawPanel виджет на фрейм, а затем по щелчку мыши, вызывается метод repint(). Но этот метод repaint() вызывается с использованием frame - объекта JFrame. В соответствии с моим основным понятием java, если я вызываю метод с использованием объекта, этот метод должен быть в этом классе или в каком-то Super классе. Я не вижу, как вызов repaint() на frame вызовет компонент краски MyDrawPanel. Я сделал некоторые копать, чтобы увидеть, если JFrame и JPanel одни и те же иерархии, и вот что я нашел:

object -> component (имеет перекрашивать метод) -> container (имеет paintcomponent метод) ->

 `jcomponent` --> `jpanel` 

     `window` --> `frame` --> `jframe` 

Так что я подумал, что с JFrame и JPanel оба получают paintComponent и repaint методы, может быть я могу продлить Jframe создать MyDrawPanel вместо Jpanel и он должен работать нормально. Но это не так. Он компилируется отлично, но исключает время выполнения.

Это действительно расстраивает. Может быть, я не получаю концепции GUI или мои основы все еще слабы. Пожалуйста, дайте мне знать, если я упустил что-то действительно глупо.

+1

Можете ли вы добавить исключение 'Получение? – APerson

ответ

2

Давайте начнем с paintComponent должны действительно назвать super.paintComponent перед выполнением любого изготовленного на заказ живописи

Затем перейти на вы действительно должны читать Painting in AWT and Swing и Performing Custom Painting для лучшего понимания того, как покрасочные работы в Swing. repaint не вызывает непосредственно paintComponent, он запрашивает RepaintManager, чтобы запланировать событие paint в очереди событий, которое в какой-то момент в будущем обрабатывается потоком диспетчеризации событий, который затем обрабатывает событие paint на основе потребностей контейнер

Так что я подумал, что с JFrame и JComponent оба получают paintComponent

нет, они этого не делают.JFrame (и это родительский класс) не имеют paintComponent метод

может быть я могу продлить JFrame создать MyDrawPanel вместо JPanel и он должен работать нормально»

Нет, вы не должны, кроме JFrame, не имеющего paintComponent, есть много других событий, которые могут помешать любой пользовательской картине, которую вы могли бы попробовать и выполнить на JFrame, и вы должны продолжить структурировать свой код так, как это

+0

n он даже не должен компилироваться, если у JFrame нет компонента paint. Он отлично компилируется, но во время выполнения - C: \ JAVAHOME> Java SimpleGui3C Исключение в потоке «основного» java.lang.IllegalArgumentException: добавление окна в контейнер в java.awt.Container.checkNotAWindow (контейнер. Java: 490) на java.awt.Container.addImpl (Container.java:1091) на java.awt.Container.add (Container.java:438) на SimpleGui3C.go (SimpleGui3C.java:24) на SimpleGui3C.main (SimpleGui3C.java:11) –

+0

Я могу отпустить все. Но как вызывать перерисовку в кадре, называет paintcomponent MyDrawPanel. Эта штука подтачивает меня. –

+0

@EolElement Добавить '@ Override' в метод' paintComponent' в вашем 'JFrame', тогда он не будет компилироваться. Когда вы создаете метод в своем классе под названием 'paintComponent', вы только что создали метод. Вы ошибаетесь, потому что пытаетесь добавить окно в другое окно, что является незаконной операцией – MadProgrammer

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

  • Нет связанных вопросов^_^