JPanel & JScrollPane and error rendering

My English is bad, but I will try to explain. I have a question. In the JPanel, I draw a line .... they should go outside of the JPanel, and the JScrollPane should theoretically show the entire panel, but it doesn't update and does not show all the lines that were released for the panel area.

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();
            }
        });
    }
}

      

+3


source to share


2 answers


I am assuming that you are trying to draw to a JPanel and then expect the JPanel to be larger to accommodate your drawing, and not only does this not work for you, but it loses the drawing if you call repaint () on the JPanel.

If yes, then

  • Just because you go beyond the size of a JPanel or other JComponent, you will not automatically grow that component as the component itself does not have the "knowledge" that you go beyond it. If you want to resize the component, you need to do it yourself.
  • Your best bet is for the JPanel to set its own size by overriding its method getPreferredSize()

    . This will prevent the other code from being reset to a different size.
  • You don't want to receive component graphics by calling getGraphics()

    . The resulting graphic is short-lived, and whatever is painted will disappear the next time paint (...) or paintComponent () is called. It's ok to call getGraphics () on a BufferedImage, but not on a component or JComponent (unless you have a good reason to do this and don't know how to protect the Graphics object to be null).
  • Override JPanel or some other JComponent and apply override method for paintComponent(...)

    that component. If you are using BufferedImage then you are painting the BufferedImage in this paintComponent method.


For example:

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);
      }
   }
}

      

+5


source


Referring to this line:

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

      



Drawing lines using graphics do not extend beyond the bounds of the graphic. This means that the lines do not actually go beyond the panel size. Before drawing lines, you need to resize the panel. See if this works:

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);

      

+1


source







All Articles