2015-02-01 2 views
1

Ниже мой код рисует бассейн и в то же время рассчитывает его объем.Мой метод вызывается, но он не рисует линии

Этот метод является paintSwimmingPool(), который отлично работает при вызове методом stateChanged() listener. Однако проблема в том, что я хочу рисовать прямоугольник при запуске программы. Я добавил в какое-то консольное сообщение, чтобы помочь отладку, который говорит мне, что метод вызывается правильно из метода createGUI(). Но почему paintSwimmingPool() ничего не рисует на панели? Извините, я потратил довольно много времени на решение этого, но не получил.

Благодарим вас за любые указатели.

import java.awt.Color; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Frame; 
import java.awt.Graphics; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.JTextField; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SwimingPoolCalculator implements ChangeListener { 

    private JFrame frame; 
    private JPanel primaryJPanel, drawingJPanel; 
    private JLabel deepJLabel, shallowJLabel; 
    private JSlider deepJSlider, shallJSlider; 
    private JTextField resultTextField; 

    final private int xPos = 20; 
    final private int yPos = 20; 
    final private int swimmingPoolLength = 200; 
    final private int swimmingPoolWidth = 50; 

    public static void main(String[] args) { 

     SwimingPoolCalculator swimingPoolCalculator = new SwimingPoolCalculator(); 

     swimingPoolCalculator.createGUI(); 

    } 

    private void createGUI(){ 

     frame = new JFrame("Swiming Pool Calculator"); 

     primaryJPanel = new JPanel(); 
     primaryJPanel.setPreferredSize(new Dimension(250, 500)); 

     drawingJPanel = new JPanel(); 
     drawingJPanel.setPreferredSize(new Dimension(250, 300)); 
     drawingJPanel.setBackground(Color.yellow); 

     shallowJLabel = new JLabel("S End"); 
     deepJLabel = new JLabel("D End"); 

     shallJSlider = new JSlider(JSlider.HORIZONTAL, 10, 100, 10); 
     deepJSlider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100); 

     shallJSlider.addChangeListener(this); 
     deepJSlider.addChangeListener(this); 

     resultTextField = new JTextField(15); 

     primaryJPanel.add(drawingJPanel); 
     primaryJPanel.add(shallowJLabel); 
     primaryJPanel.add(shallJSlider); 
     primaryJPanel.add(deepJLabel); 
     primaryJPanel.add(deepJSlider); 
     primaryJPanel.add(resultTextField); 

     frame.getContentPane().add(primaryJPanel); 
     frame.pack(); 
     frame.setVisible(true); 

     // why the first call does not draw any line? 
     paintSwimmingPool(deepJSlider.getValue(), shallJSlider.getValue()); 

    } 

    private void paintSwimmingPool(int deepEnd, int shallowEnd){ 

     Graphics drawingBoard = drawingJPanel.getGraphics(); 

     drawingBoard.setColor(Color.yellow); 
     drawingBoard.fillRect(0, 0, 250, 250); 
     drawingBoard.setColor(Color.black); 

     drawingBoard.drawLine(xPos, yPos, xPos + swimmingPoolLength, yPos); // the top line 
     drawingBoard.drawLine(xPos, yPos, xPos, yPos + deepEnd); // the left line 
     drawingBoard.drawLine(xPos + swimmingPoolLength, yPos, xPos + swimmingPoolLength, yPos + shallowEnd); // the right line 
     drawingBoard.drawLine(xPos, yPos + deepEnd, xPos + swimmingPoolLength, yPos + shallowEnd); // the bottom line 

    } 

    private void calculateVolume(double averageDepth){ 

     int swimmingPoolVolume = (int)(averageDepth * swimmingPoolLength * swimmingPoolWidth); 

     resultTextField.setText("Volume: " + swimmingPoolVolume); 

    } 

    @Override 
    public void stateChanged(ChangeEvent e) { 

     int shallowEnd = shallJSlider.getValue(); 
     int deepEnd = deepJSlider.getValue(); 

     double averageDepth = (shallowEnd + deepEnd)/2; 

     paintSwimmingPool(deepEnd, shallowEnd); 

     calculateVolume(averageDepth); 

    } 

} 
+0

возможно дубликат [Чертеж объекта с использованием GetGraphics() без расширения фрейма] (http://stackoverflow.com/questions/15986677/ рисование-объект-использование-getgraphics-without-extend-jframe) – immibis

+0

Взгляните на [Живопись в AWT и Swing] (http://www.oracle.com/technetwork/java/painting-140037.html) и [Выполнение пользовательской живописи] (http://docs.oracle.com/javase/tutorial/uiswing/painting/) – MadProgrammer

ответ

3

Вы не можете сделать так, правильная техника

  • переопределить метод paintComponent() в подклассе JPanel и использовать параметр Graphics вместо этого.
  • вызов перекрасить(), чтобы вызвать перерисовку вместо вашего paintSwimmingPool() метод
  • параметры перемещения т.е. deepEnd и shallowEnd в поля и ссылки на них из вашего paintComponent() метод - внутренний класс, мы сможем «увидеть» эти поля. В идеальном случае они были бы в отдельной модели, разделяемой панелью чертежа и управляющим кодом, но внутренний класс выполняет свою работу.
  • Посмотрите на oracle tutorial on custom painting

Полностью работал пример

public class SwimingPoolCalculator implements ChangeListener { 

    private JFrame frame; 
    private JPanel primaryJPanel, drawingJPanel; 
    private JLabel deepJLabel, shallowJLabel; 
    private JSlider deepJSlider, shallJSlider; 
    private JTextField resultTextField; 

    final private int xPos = 20; 
    final private int yPos = 20; 
    final private int swimmingPoolLength = 200; 
    final private int swimmingPoolWidth = 50; 
    private int deepEnd; // <== moved to fields 
    private int shallowEnd; // <== moved to fields 

    private class InnerDrawingPanel extends JPanel { 
     @Override 
     protected void paintComponent(Graphics drawingBoard) { 
      drawingBoard.setColor(Color.yellow); // <== drawing code now here 
      drawingBoard.fillRect(0, 0, 250, 250); 
      drawingBoard.setColor(Color.black); 

      drawingBoard.drawLine(xPos, yPos, xPos + swimmingPoolLength, yPos); // the top line 
      drawingBoard.drawLine(xPos, yPos, xPos, yPos + deepEnd); // the left line 
      drawingBoard.drawLine(xPos + swimmingPoolLength, yPos, xPos + swimmingPoolLength, yPos + shallowEnd); // the right line 
      drawingBoard.drawLine(xPos, yPos + deepEnd, xPos + swimmingPoolLength, yPos + shallowEnd); // the bottom line 
     } 
    } 

    public static void main(String[] args) { 

     SwimingPoolCalculator swimingPoolCalculator = new SwimingPoolCalculator(); 

     swimingPoolCalculator.createGUI(); 

    } 

    private void createGUI(){ 

     frame = new JFrame("Swiming Pool Calculator"); 

     primaryJPanel = new JPanel(); 
     primaryJPanel.setPreferredSize(new Dimension(250, 500)); 

     drawingJPanel = new InnerDrawingPanel(); // <== use inner class 
     drawingJPanel.setPreferredSize(new Dimension(250, 300)); 
     drawingJPanel.setBackground(Color.yellow); 

     shallowJLabel = new JLabel("S End"); 
     deepJLabel = new JLabel("D End"); 

     shallJSlider = new JSlider(JSlider.HORIZONTAL, 10, 100, 10); 
     deepJSlider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100); 

     shallJSlider.addChangeListener(this); 
     deepJSlider.addChangeListener(this); 

     resultTextField = new JTextField(15); 

     primaryJPanel.add(drawingJPanel); 
     primaryJPanel.add(shallowJLabel); 
     primaryJPanel.add(shallJSlider); 
     primaryJPanel.add(deepJLabel); 
     primaryJPanel.add(deepJSlider); 
     primaryJPanel.add(resultTextField); 

     frame.getContentPane().add(primaryJPanel); 
     frame.pack(); 
     frame.setVisible(true); 

     // why the first call does not draw any line? 
     shallowEnd = deepJSlider.getValue(); // <== now update fields 
     deepEnd = shallJSlider.getValue(); 
     drawingJPanel.repaint();  // <== trigger repaint 

    } 


    private void calculateVolume(double averageDepth){ 

     int swimmingPoolVolume = (int)(averageDepth * swimmingPoolLength * swimmingPoolWidth); 

     resultTextField.setText("Volume: " + swimmingPoolVolume); 

    } 

    @Override 
    public void stateChanged(ChangeEvent e) { 

     shallowEnd = shallJSlider.getValue(); // <== update fields 
     deepEnd = deepJSlider.getValue(); 

     double averageDepth = (shallowEnd + deepEnd)/2; 


     drawingJPanel.repaint(); // <== trigger repaint 
     calculateVolume(averageDepth); 

    } 

} 
+0

(кашель) 'super.paintComponent' (кашель) – MadProgrammer

+0

Мне стыдно !! – Adam

+1

'g.drawImage (image, 0, 0, null);' должно быть 'g.drawImage (image, 0, 0, this);' as 'JPanel' реализует интерфейс' ImageObserver' через 'JComponent'. Также может возникнуть проблема не в использовании контекста «Graphics», который вы создаете ('image.getGraphics();') в некоторых системах, но это проблема рабочего процесса. – MadProgrammer

0

Свинг, вероятно, перекрашивает JPanel после того, как вы нарисовали его. Swing может перекрасить компоненты в любое время по любой причине. По этой причине вы не должны использовать getGraphics.

Вместо этого вам необходимо создать свой собственный класс компонентов (расширение существующего компонента, например JPanel), и переопределить paintComponent.

Для получения более подробной информации см. this question.

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