paintComponent is not erasing JPanel - java

The program is to display 3 buttons on the JPanel. The program is compiled successfully. The GUI Window then appears and is empty. When I minimise the window and then maximise it again the Buttons appear. On doing this again another set of Buttons appear. The button keeps on appearing when the window is refreshed and the older data is kept intact.
JPanel Class
class MyJPanel extends JPanel {
JButton jb1, jb2, jb3;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
jb1 = new JButton();
jb2 = new JButton("Green");
jb3 = new JButton("Blue");
//g.drawString("Welcome!", 100, 100);
ImageIcon img = new ImageIcon("next.png");
jb1.setIcon(img);
jb1.setToolTipText("Button 1");
this.add(jb1);
this.add(jb2);
this.add(jb3);
}
}
JFrame Class
class MyJFrame extends JFrame {
MyJPanel mjp;
public MyJFrame(String title) {
super(title);
mjp = new MyJPanel();
Container ct = getContentPane();
ct.add(mjp);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Driver Class
class Gui5JButton {
public static void main(String[] args) {
MyJFrame mjf = new MyJFrame("Prakhar");
mjf.repaint();
}
}

paintComponent is called everytime your panel needs to be redraw, so everytime you minimize the window it will put the button again. If I understood what you want to do correctly, you need to remove the override and put this code :
jb1 = new JButton();
jb2 = new JButton("Green");
jb3 = new JButton("Blue");
//g.drawString("Welcome!", 100, 100);
ImageIcon img = new ImageIcon("next.png");
jb1.setIcon(img);
jb1.setToolTipText("Button 1");
this.add(jb1);
this.add(jb2);
this.add(jb3);
in the constructor of your MyJPanel class.

Related

How to add a background image in JPanel?

I did exactly according to the excellent guide but it does not work, I want to click a button that will change the background of the program. I would love to make the picture change
Code Guide https://stackhowto.com/how-to-set-background-image-in-java-swing/
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Display an image in the background");
final ImageIcon icon = new ImageIcon("background.png");
JTextArea text = new JTextArea()
{
Image img = icon.getImage();
// instance initializer
{setOpaque(false);}
public void paintComponent(Graphics graphics)
{
graphics.drawImage(img, 0, 0, this);
super.paintComponent(graphics);
}
};
JScrollPane pane = new JScrollPane(text);
Container content = frame.getContentPane();
content.add(pane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(3);
frame.setSize(400, 300);
frame.setVisible(true);
}
}

How to make the roll button the default allowing enter press?

I wrote a program to randomly select an image and display it in the window every time a button is pressed. Mow I am trying to figure out how to make the "Roll Dice" button the default allowing enter press.
Driver:
public class MCobbM10A1 {
static int SCREEN_WIDTH = 500;
static int SCREEN_HEIGHT = 600;
static WidgetPanel widget;
static GraphicPanel myPanel;
public static void main(String[] args) {
JFrame myFrame = new JFrame("Dice Roller");
JFrame.setDefaultLookAndFeelDecorated(true);
myPanel = new GraphicPanel();
myPanel.setBounds(0, 0, 500, 200);
myFrame.add(myPanel);
JPanel lastPanel = new JPanel();
myFrame.add(lastPanel);
widget = new WidgetPanel();
widget.setBounds(0, 250, 500, 300);
myFrame.add(widget);
widget.rollButton.addActionListener((ActionEvent newRoll) -> {
new MCobbM10A1().myNewRollButtonPressed();
});
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.pack();
myFrame.setVisible(true);
myFrame.setBounds(0, 0, 500, 300);
}
private void myNewRollButtonPressed() {
myPanel.newRoll();
}
}
And here is the WidgetPanel:
public class WidgetPanel extends JPanel {
JButton rollButton;
WidgetPanel() {
this.setBackground(Color.WHITE);
this.setLayout(new BorderLayout());
rollButton = new JButton();
rollButton.setBounds(350, 200, 100, 25);
rollButton.setText("Roll Dice");
this.add(rollButton);
JLabel fixBug = new JLabel();
this.add(fixBug);
}
}
how to make the "Roll Dice" button the default allowing enter press.
You assign the default button to the JRootPane of your frame.
frame.getRootPane().setDefaultButton(…);
One way to do this is:
#Override
public void addNotify()
{
super.addNotify();
JFrame frame = (JFrame)SwingUtilities.windowForComponent( rollButton );
frame.getRootPane().setDefaultButton(rollButton);
}
The addNotify() method is invoked when a panel is added to the frame.
Unrelated to your question but why are you creating a new object for each roll?
widget.rollButton.addActionListener((ActionEvent newRoll) -> {
new MCobbM10A1().myNewRollButtonPressed(); // <--- new MCobbM10A1 object
});
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.pack();
myFrame.setVisible(true);
myFrame.setBounds(0, 0, 500, 300);
}
private void myNewRollButtonPressed() {
myPanel.newRoll();
}
Why not just do this?
widget.rollButton.addActionListener((ae) ->
myPanel.newRoll());

I'm trying to insert a JPanel into a JFrame but the JPanel dont show off

So i have 3 classes.The first one is for creating a frame :
public class DrawingFrame extends JFrame{
public DrawingFrame(){
JFrame abc = new JFrame("TEST");
abc.setSize(600,500);
abc.setLayout(null);
abc.setVisible(true);
abc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolbar top = new Toolbar();
abc.add(top);
}
}
The second one is for JPanel :
public class Toolbar extends JPanel{
public Toolbar(){
JPanel top = new JPanel();
top.setLayout(null);
top.setVisible(true);
top.setPreferredSize(new Dimension(150,150));
top.setBackground(Color.RED);
JButton buton = new JButton("Hello!");
buton.setBounds(40, 40, 40, 40);
top.add(buton);
}
}
And this is the main class:
public class Main {
public static void main(String[] args) {
DrawingFrame a = new DrawingFrame();
}
}
My code prints out the frame but not with the panel.How i can fix this ?
First, you don't need to create an instance JPanel in a subclass of JPanel, same for JFrame. The instance is already one.
Use this to access the instance itself :
public Toolbar(){
this.setLayout(null);
this.setVisible(true);
this.setPreferredSize(new Dimension(150,150));
this.setBackground(Color.RED);
JButton buton = new JButton("Hello!");
buton.setBounds(40, 40, 40, 40);
this.add(buton);
}
Second, if you use a null layout, you need to set the bounds of each componennt, as mention in Doing Without a Layout Manager (Absolute Positioning)
Creating a container without a layout manager involves the following steps.
Set the container's layout manager to null by calling setLayout(null).
Call the Component class's setbounds method for each of the container's children.
Call the Component class's repaint method.
So adding the bounds to the JPanel will be enough with : top.setBounds(0,0,150,150); for example
class DrawingFrame extends JFrame{
public DrawingFrame(){
super("TEST");
this.setSize(600,500);
this.setLayout(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolbar top = new Toolbar();
top.setBounds(0, 0, 150, 150);
this.add(top);
}
}
class Toolbar extends JPanel{
public Toolbar(){
this.setLayout(null);
this.setVisible(true);
this.setPreferredSize(new Dimension(150,150));
this.setBackground(Color.RED);
JButton buton = new JButton("Hello!");
buton.setBounds(40, 40, 40, 40);
this.add(buton);
}
}
And this will look like what you asked (in term of dimension and absolute position)
Move abc.setVisible(true); to the end
Also, use this instead of create new panel in toolbar. Same is in the case of frame as well
So, the below code will work:
public static void main(String...s) {
DrawingFrame a = new DrawingFrame();
}
class DrawingFrame extends JFrame{
public DrawingFrame(){
super("TEST");
this.setLayout(new FlowLayout());
Toolbar top = new Toolbar();
this.add(top);
this.setSize(600,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
class Toolbar extends JPanel{
public Toolbar(){
this.setLayout(new FlowLayout());
this.setPreferredSize(new Dimension(150,150));
this.setBackground(Color.RED);
JButton buton = new JButton("Hello!");
buton.setBounds(40, 40, 40, 40);
this.add(buton);
this.setVisible(true);
}
}

Sending variables between classes

I have a JFrame class and a JPanel class.
When I click on a button in my JFrame my variable addIp take the entered String.
How can I access to this variable in my JPanel class ?
Here's my JFrame class:
public class Window extends JFrame{
public static void main(String[] args) {
new Window();
}
}
public Window()
{
this.setSize(1000,400);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setTitle("Assignment2 - CPU temperature");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container = new JPanel(new BorderLayout());
north = new JPanel();
north.setLayout(new BorderLayout());
ip = new JButton ("New");
north.add(ip, BorderLayout.WEST);
print = new JButton ("Print");
north.add(print,BorderLayout.EAST);
JPanel centerPanel = new JPanel();
centerPanel.add(new JLabel("Time Step (in s): "));
timeStep = new JTextArea("0.1",1,5);
centerPanel.add(timeStep);
start = new JButton("OK");
stop = new JButton("STOP");
ListenForButton lForButton = new ListenForButton();
ip.addActionListener(lForButton);
centerPanel.add(start);
centerPanel.add(stop);
north.add(centerPanel, BorderLayout.CENTER);
west = new JPanel();
JLabel temp = new JLabel("°C");
west.add(temp);
container.add(north, BorderLayout.NORTH);
container.add(west,BorderLayout.WEST);
container.add(pan, BorderLayout.CENTER);
this.setContentPane(container);
this.setVisible(true);
}
public class ListenForButton implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(e.getSource()==ip)
{
options.add(address);
options.add(address_t);
options.add(port);
options.add(port_t);
int result = JOptionPane.showConfirmDialog(null, options, "Please Enter an IP Address and the port wanted", JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION)
{
if(!address_t.getText().isEmpty())
{
addIp=address_t.getText();
}
}
}
And I want the addIP variable be accessible in my JPanel class:
public class GraphDisplay extends JPanel implements ActionListener {
double rand, lastrand, max, min, total, degr, average, temp, length;
ArrayList<Double> randL = new ArrayList<>();
ArrayList<Integer> tL = new ArrayList<>();
ArrayList<String> dateL = new ArrayList<>();
int lastT = 0;
Color red = new Color(255, 0, 0);
Color green = new Color(0, 200, 0);
Color blue = new Color(0, 0, 200);
Color yellow = new Color(200, 200, 0);
int i, k = 0, inc, j, t;
public GraphDisplay() {
super();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
I copied you just the beginning of the class because the rest isn't interesting for this kind of problem.
You have several options:
Have the object that holds the information "push" it into the other object. To do this, your Window class would need to hold an instance of the GraphDisplay class, and call a method that GraphDisplay has, say, setIPaddress(String ip), passing in the String into GraphDisplay. Note that the instance hold by Window has to be the visualized GraphDisplay instance, and not any old instance.
Or you could have GraphDisplay "pull" the information in. Here Window would notify any listeners that the addIP variable has changed, and so the listeners, here this could be the GraphDisplay instance, could call getAddIP() from Window and thereby get the new value. To do this, you'd have to use Swing's notification mechanism, such as a ChangeListener or a PropertyChangeListener.

How to add 3 rectangles to Jpanel in java?

I'm trying to add three rectangles to the center of BorderLayout and I'm completely lost. My finished program needs to increase the height of the rectangle as the sliders move but I'm trying to figure out how to intitally draw these three rectangles to the jpanel. I'm so lost. My code is below.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ShowColors extends JPanel
{
public static void main(String args[])
{
JFrame frame = new JFrame();
JPanel main = new JPanel(new BorderLayout());
main.setSize(2000, 1000);
frame.setContentPane(main);
JPanel jp1 = new JPanel(new GridLayout(0, 1));
JPanel jp2 = new JPanel(new GridLayout(2,3));
JPanel jp3 = new JPanel(new GridLayout(1, 3));
jp1.setPreferredSize(new Dimension(90, 800));
jp2.setPreferredSize(new Dimension(1000, 150));
jp3.setPreferredSize(new Dimension(800, 600));
JRadioButton rb1 = new JRadioButton("Decimal", true);
JRadioButton rb2 = new JRadioButton("Binary");
JRadioButton rb3 = new JRadioButton("Hex");
JRadioButton rb4 = new JRadioButton("Octal");
JButton jb1 = new JButton("RESET");
ButtonGroup group = new ButtonGroup();
group.add(rb1);
group.add(rb2);
group.add(rb3);
group.add(rb4);
JSlider jRed = new JSlider(0,255);
JSlider jGreen = new JSlider(0,255);
JSlider jBlue = new JSlider(0,255);
jRed.setPaintLabels(true);
jRed.setPaintTicks(true);
jRed.setMinorTickSpacing(5);
jRed.setMajorTickSpacing(50);
jRed.setValue(0);
jGreen.setPaintLabels(true);
jGreen.setPaintTicks(true);
jGreen.setMinorTickSpacing(5);
jGreen.setMajorTickSpacing(50);
jGreen.setValue(0);
jBlue.setPaintLabels(true);
jBlue.setPaintTicks(true);
jBlue.setMinorTickSpacing(5);
jBlue.setMajorTickSpacing(50);
jBlue.setValue(0);
JLabel labelR = new JLabel("Red", JLabel.CENTER);
JLabel labelG = new JLabel("Green", JLabel.CENTER);
JLabel lableB = new JLabel("Blue", JLabel.CENTER);
jp1.add(rb1);
jp1.add(rb2);
jp1.add(rb3);
jp1.add(rb4);
jp1.add(jb1);
jp2.add(labelR);
jp2.add(labelG);
jp2.add(lableB);
jp2.add(jRed);
jp2.add(jGreen);
jp2.add(jBlue);
main.add(jp1, BorderLayout.WEST);
main.add(jp2, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g)
{
super.paint(g);
g.drawRect(0, 0, 10, 20);
g.setColor(Color.RED);
g.fillRect(0, 0, 10, 20);
g.drawRect(10, 0, 10, 20);
g.setColor(Color.GREEN);
g.fillRect(10, 0, 10, 20);
g.drawRect(20, 0, 10, 20);
g.setColor(Color.BLUE);
g.fillRect(20, 0, 10, 20);
}
}
here is my layout and i want the rectangles in the center.
I think you just need a simple subclass of JPanel and override paintComponent(). Something like this should get you going:
import javax.swing.*;
import java.awt.*;
public class Canvas extends JPanel {
// TODO member variables for rectangle size/color
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(10,10,100,50);
g.drawRect(10,80,100,50);
}
}
EDIT:
Actually, I guess you really don't need a "Canvas" class, you can just use a plain JPanel as #MadProgrammer suggests. What you do need is a class that will encapsulate the Rectangle behavior, which can just be a simple JComponent that gets added to the JPanel that holds your three rectangles.
Here's a working solution, imports excluded for brevity:
public class ShowColors {
class Rectangle extends JComponent implements ChangeListener {
private JSlider slider;
private Color color;
public Rectangle(JSlider slider, Color color) {
this.slider = slider;
this.color = color;
this.setPreferredSize(new Dimension(250, 250));
slider.addChangeListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int value = slider.getValue();
g.setColor(color);
g.fillRect(10,10,100,value);
}
#Override
public void stateChanged(ChangeEvent arg0) {
this.repaint();
}
}
public ShowColors() {
JFrame frame = new JFrame();
JPanel main = new JPanel(new BorderLayout());
main.setSize(2000, 1000);
frame.setContentPane(main);
JPanel jp1 = new JPanel(new GridLayout(0, 1));
JPanel jp2 = new JPanel(new GridLayout(2, 3));
jp1.setPreferredSize(new Dimension(90, 800));
jp2.setPreferredSize(new Dimension(1000, 150));
JRadioButton rb1 = new JRadioButton("Decimal", true);
JRadioButton rb2 = new JRadioButton("Binary");
JRadioButton rb3 = new JRadioButton("Hex");
JRadioButton rb4 = new JRadioButton("Octal");
JButton jb1 = new JButton("RESET");
ButtonGroup group = new ButtonGroup();
group.add(rb1);
group.add(rb2);
group.add(rb3);
group.add(rb4);
JSlider jRed = buildSlider();
JSlider jGreen = buildSlider();
JSlider jBlue = buildSlider();
JLabel labelR = new JLabel("Red", JLabel.CENTER);
JLabel labelG = new JLabel("Green", JLabel.CENTER);
JLabel lableB = new JLabel("Blue", JLabel.CENTER);
jp1.add(rb1);
jp1.add(rb2);
jp1.add(rb3);
jp1.add(rb4);
jp1.add(jb1);
jp2.add(labelR);
jp2.add(labelG);
jp2.add(lableB);
jp2.add(jRed);
jp2.add(jGreen);
jp2.add(jBlue);
JPanel canvas = new JPanel();
canvas.setLayout(new FlowLayout());
canvas.setPreferredSize(new Dimension(800, 600));
canvas.add(new Rectangle(jRed, Color.RED));
canvas.add(new Rectangle(jGreen, Color.GREEN));
canvas.add(new Rectangle(jBlue, Color.BLUE));
main.add(jp1, BorderLayout.WEST);
main.add(jp2, BorderLayout.SOUTH);
main.add(canvas, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static JSlider buildSlider() {
JSlider slider = new JSlider(0, 255);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(50);
slider.setValue(50);
return slider;
}
public static void main(String args[]) {
new ShowColors();
}
}
And here's what it looks like:
Don't override paint, painting in Swing is achieved by a delicate and complicated chain of methods, which is easily broken. Instead, override it's paintComponent method instead. See Painting in AWT and Swing for more details
Having said that, don't add all your components to the same panel onto which you want to draw, you'll end up painting underneth all the components. Instead, create a separate JPanel which acts as the paint surface and another JPanel which acts as the controller (containing the controls and the paint surface). Use setters and getters to change the state of the paint surface. See Performing Custom Painting for more details.
Create some kind of "drawable" object, which knows how to paint itself and what it should use to paint itself (the color)
Create some kind of List (in the paint surface class) which can hold the objects which you want to paint. Within in it's paintComponent you will will loop through the list and request that each object paint itself, passing it the Graphics context. Take a look at 2D Graphics for more details
This previous answer may also help

Categories

Resources