I'm trying to get JButtons which have been added to a JPanel to show up during the execution of a program, however they only appear when I hover the mouse of them, they remain invisible until then.
Below is my code, I've tried repaint() and revalidate() with no luck.
There also seems to be an issue with the height of the JPanel, it seems to be larger than the main Window for some reason
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public final class SideMenu extends JPanel implements ActionListener{
private final int width;
private final int height;
public SideMenu(int width, int height){
this.width = width;
this.height = height;
this.setLayout(new GridLayout(0,1));
this.add(new JButton("button1"));
this.add(new JButton("button2"));
this.add(new JButton("button3"));
this.revalidate();
this.repaint();
}
#Override
public void paint(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
public static void main(String[] args){
int width = 300, height = 400;
JFrame jf = new JFrame();
jf.setTitle("Fish Tank");
jf.setSize(width, height);
jf.setVisible(true);
jf.setLayout(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
///jf.setResizable(false);
SideMenu side_menu = new SideMenu(100,height);
jf.add(side_menu);
side_menu.setBounds(200, 0, 100, height);
}
}
Use paintComponent(..) method instead of paint(..):
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
}
Read more about custom paintings.
Also call jf.setVisible(true); at the end of construction of GUI, when you add all components to JFrame.
Related
I have a JPanel in my java code and I want to set its size, I have used JPanel.setSize(500,500); and JPanel.setSize(new Dimension(500,500)); but both are not working. Please tell how I can set the size of JPanel?
Most Swing layout managers respect a component's preferredSize and not its size. You could call setPreferredSize(new Dimension(500, 500)), but this can be overridden later in your code, and can lead to an inflexible GUI. Better to override the JPanel's getPreferredSize() method and return a calculated Dimension that works best in all situations.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
public class PrefSizePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
public Dimension getPreferredSize() {
// update as per Marco:
if (super.isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// just for fun
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, Color.red, 20, 20, Color.blue, true));
g2.fillOval(0, 0, 2 * getWidth(), 2 * getHeight());
}
private static void createAndShowGUI() {
PrefSizePanel paintEg = new PrefSizePanel();
JFrame frame = new JFrame("PrefSizePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Which displays as
I am working on learning how to create custom components. I would like to be able to include all of the methods that it calls to start with and to be able to change even the border method. Below my code does not repaint the paintBorder(...) method
public void paintBorder(Component t, Graphics g, int x, int y, int h, int w) {
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
Why would this not be being painted. The code in the paintComponent(...) does work and paint the circle but what if I want to set the border to something different or even if I just want to see a message go to the console with a println(...).
Paint Call:
There are three methods called
paintComponent()
paintBorder()
paintChildren()
How can I get my paintBorder() to be called? I would imagine that if I make a instance of this in another class than I should be able to call repaint() which calls update which intern schedules a call to paint which calls the three methods listed above (paintComponent, paintBorder, paintChildren)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testBall {
public static void main(String[] args) {
new testBall();
}
public testBall() {
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
testPane.add(new Ball(30,30,10));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class MyBall extends JComponent{
private static final long serialVersionUID = 1L;
public static Color colorBall = Color.red;
public MyBall() {
super();
System.out.println("MyBall (0)");
}
public MyBall(int x, int y, int diameter){
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
}
public void paintBorder(Graphics g) {
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(0, 0, 50, 50);
System.out.println("paintComponent");
}
public void paint(Graphics g) {
super.paint(g);
paintComponent(g);
paintBorder(this, g,10,10,10,10);
paintChildren(g);
System.out.println("Paint");
}
}
Working Code: I was creating an instance of a different ball class which was something that I did not see. If a person is going to over write the paintBorder(...) method in a class the extends JComponent(...) how should the border be painted? Does anyone have any good links for such a task?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testBall
{
public static void main(String[] args)
{
new testBall();
}
public testBall()
{
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
testPane.add(new MyBall(30,30,10));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class MyBall extends JComponent
{
private static final long serialVersionUID = 1L;
private Color colorBall = Color.red;
public void setColorBall(Color c)
{
this.colorBall = c;
}
public MyBall()
{
super();
System.out.println("MyBall (0)");
}
public MyBall(int x, int y, int diameter)
{
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
}
public void paintBorder(Graphics g)
{
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(0, 0, 50, 50);
System.out.println("paintComponent");
}
public void paint(Graphics g)
{
super.paint(g);
paintComponent(g);
paintBorder(g);
paintChildren(g);
System.out.println("Paint");
}
}
There is no such method in JComponent
public void paintBorder(Component t, Graphics g, int x, int y, int h, int w)
It's method of border so it's never invoked in JComponent. Override
protected void paintBorder(Graphics g)
Instead and add your code there.
I am trying to create my own component for swing, but when i try to paint the border of it with drawRect, it only draws the left and top edges! Why is that, and how can it be fixed?
Here is my paintComponent method:
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.red);
g.drawRect(0, 0, getWidth(), getHeight());
}
Screenshot:
I am trying to create my own component for swing, but when i try to paint the border of it with drawRect,
Why are you trying to draw a Border. Swing supports borders. if your component needs a border then you should be using:
setBorder( new LineBorder(Color.RED) );
and let swing draw the border for you.
it only draws the left and top edges!
I think you should be using:
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
Maybe this will help you as a starting point:
package de.professional_webworkx.graphics;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class DrawFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = -1285962479945295143L;
private JPanel northPanel;
public DrawFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Draw");
this.setLayout(new BorderLayout());
this.getContentPane().add(createNorthPanel(), BorderLayout.BEFORE_FIRST_LINE);
this.getContentPane().add(new DrawPanel(), BorderLayout.CENTER);
this.setSize(1024, 768);
this.setVisible(true);
}
public JPanel createNorthPanel() {
northPanel = new JPanel();
northPanel.setBackground(Color.MAGENTA);
JLabel jLabel = new JLabel("XXXXXXXXXXXX");
jLabel.setForeground(Color.WHITE);
northPanel.add(jLabel);
return northPanel;
}
public static void main(String[] args) {
new DrawFrame();
}
}
DrawPanel.class
package de.professional_webworkx.graphics;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 4949248244138855737L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.drawRect(10, 10, getWidth()/2, getHeight()/2);
g.setColor(Color.YELLOW);
g.fillRect(11, 11, getWidth()/2-1, getHeight()/2-1);
g.draw3DRect(10, getHeight()/2+20, 600, 280, true);
}
}
Patrick
UPDATE: Thanks to camickr.
I want to set up a mathematical (where y grows up not down) coordinate space from (-1, -1) to (+1, +1) and have it fit in the window regardless of the window size.
I am using an anonymous JComponent subclass in Java SE 7 and casting the incoming Graphics in paintComponent to Graphics2D and then drawing on the Graphics2D
But the Graphics2D is set to a computer coordinate space that changes with the size of the window. How to get it to rescale according to window size and have Y go upwards? The following program should show a dark square in upper right quadrant.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class G {
public static void main (String [] args) {
JFrame frame = new JFrame(G.class.getCanonicalName());
frame.setUndecorated(true);
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
paint2D((Graphics2D)g);
}
protected void paint2D (Graphics2D g2) {
g2.draw(new Rectangle2D.Double(0.1, 0.1, 0.9, 0.9));
}
};
frame.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
Setup the coordinate system how you want, using transform() and translate(). So:
you want the origin to be at (0, height); bottom left.
then you want to flip the Y axis.
Example code:
AffineTransform tform = AffineTransform.getTranslateInstance( 0, height);
tform.scale( 1, -1);
g2.setTransform( tform);
[My edited version]:
public static void main (String [] args) {
JFrame frame = new JFrame( G2dTransform_Question.class.getCanonicalName());
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
paint2D((Graphics2D)g);
}
protected void paint2D (Graphics2D g2) {
AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
tform.scale( getWidth(), -getHeight()); // NOTE -- to make 1.0 'full width'.
g2.setTransform( tform);
g2.setColor( Color.BLUE); // NOTE -- so we can *see* something.
g2.fill( new Rectangle2D.Double(0.1, 0.1, 0.8, 0.8)); // NOTE -- 'fill' works better than 'draw'.
}
};
frame.setLayout( new BorderLayout()); // NOTE -- make the component size to frame.
frame.add( component, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
[Hovercraft's version]: Thanks Hover!
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class G {
public static final int PREF_W = 400;
public static final int PREF_H = PREF_W;
public static void main (String [] args) {
JFrame frame = new JFrame(G.class.getCanonicalName());
frame.setUndecorated(true);
JComponent component = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
AffineTransform tform = AffineTransform.getTranslateInstance( 0, getHeight());
tform.scale( 1, -1);
Graphics2D g2 = (Graphics2D) g.create();
g2.setTransform( tform);
paint2D(g2);
g2.dispose();
}
protected void paint2D (Graphics2D g2) {
g2.draw(new Rectangle2D.Double(10, 10, 20, 30));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
};
frame.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
I have a JPanel inside the JScrollPane and it does that whenever I try to scroll. Please help! How do I fix this?
EDIT
JScrollPane pane;
....
pane = new JScrollPane(GC.createGraph());
pane.setPreferredSize(new Dimension(480,480*2/3));
Placing as an answer for others to see. If you don't call the super.paintComponent, you'll get those artifacts. e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
public class ScrollPaneArtifacts extends JPanel {
private static final int SPA_WIDTH = 600;
private static final int SPA_HEIGHT = SPA_WIDTH;
#Override
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
g.setColor(Color.red);
g.drawLine(0, 0, getWidth(), getHeight());
g.drawLine(getWidth(), 0, 0, getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SPA_WIDTH, SPA_HEIGHT);
}
private static void createAndShowUI() {
JScrollPane scrollpane = new JScrollPane(new ScrollPaneArtifacts());
scrollpane.getViewport().setPreferredSize(new Dimension(400, 400));
JFrame frame = new JFrame("ScrollPaneArtifacts");
frame.getContentPane().add(scrollpane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
You do not need to call super.paintComponent you can simply clear the area to ensure no artifacts are left on the panel from the previous render (which calling super.paintComponent will do).
#Override
protected void paintComponent(Graphics g) {
g.clearRect(0,0,getWidth(),getHeight());
g.setColor(Color.red);
g.drawLine(0, 0, getWidth(), getHeight());
g.drawLine(getWidth(), 0, 0, getHeight());
}
Try this in Hovercrafts code if you like.