简体   繁体   中英

Draw Line when Button is pressed Swing

I have some problem drawing a simple line to a Frame through a JButton . The problem occurs only when I do this with a JButton . If I directly use the JPanel inside the Frame , everything is OK.

JFrame :

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

public class Fenetre extends JFrame {

    public Fenetre(){
        super("Test");
        init();
        pack();
        setSize(200,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void init() {
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());

        JButton button = new JButton("Draw line");

        button.addActionListener((e)->{
            Pane s = new Pane();
            panel.add(s);
            s.repaint();
        });

        panel.setBackground(new Color(149,222,205));

        add(button,BorderLayout.SOUTH);
        add(panel,BorderLayout.CENTER);
    }

    public static void main(String[] args){
        new Fenetre();
    }

}

And the JPanel with paintComponents() :

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

public class Pane extends JPanel {

    public void paintComponents(Graphics g){
        super.paintComponents(g);
        g.drawLine(0,20,100,20);
    }
}

A number of issues jump out at me immediately:

  1. You should be using paintComponent , not paintComponents (note the s at the end), you're too high up in the paint chain. There's also no need for either method to be public , no one outside the class should be calling it.
  2. Pane provides no sizing hints, so it's "default" size will be 0x0

Instead, it should look more like...

public class Pane extends JPanel {

    public Dimension getPreferredSize() {
        return new Dimension(100, 40);
    }

    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawLine(0,20,100,20);
    }
}

When adding components, Swing is lazy. It won't run a layout/paint pass until it has to or you ask it to. This is an optimisation, as you may add many components before needing to perform a layout pass.

To request a layout pass, call revalidate on the top level container you've updated. As a general rule of thumb, if you call revalidate , you should also call repaint to request a new paint pass as well.

public class Fenetre extends JFrame {

    public Fenetre(){
        super("Test");
        init();
        //pack();
        setSize(200,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void init() {
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());

        JButton button = new JButton("Draw line");

        button.addActionListener((e)->{
            Pane s = new Pane();
            panel.add(s);
            panel.revalidate();
            panel.repaint();
            //s.repaint();
        });

        panel.setBackground(new Color(149,222,205));

        add(button,BorderLayout.SOUTH);
        add(panel,BorderLayout.CENTER);
    }

    public static void main(String[] args){
        new Fenetre();
    }

}

That should at least get your panel to show up now

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM