Resizing Graphics2D Objects with JFrame Resize - java

I am making a GUI that has Graphics2D objects drawn on a JPanel within a JFrame. When I resize the window the Graphics2D objects reduce into a tiny rectangle. How can I set the drawing to resize with the JFrame when the user resizes the window?
I have tried using gridlayout, flowlayout, borderlayout, and settled on gridbaglayout. This helps with the resizing of btnPanel and the JButton but not for the Graphics2D objects.
Here is my self contained example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class DrawPanelMain extends JPanel {
/*
* Variables used to set the value of preferred height and width
*/
public static final double version = 0.0;
JPanel btnPanel = new JPanel();
JPanel switchPanel = new JPanel();
DrawEllipses drawEllipses = new DrawEllipses(POINT_LIST);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initializePointList();
createAndShowGui();
}
});
}
public static java.util.List<Point> POINT_LIST = new ArrayList<>();
/*
* This loop will initialize POINT_LIST with the set of points for drawing the ellipses.
* The for each loop initializes points for the top row and the second for loop draws the
* right triangle.
*/
public static void initializePointList() {
int ellipsePointsYCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620};
int ellipsePointsXCoordinate[] = {140, 200, 260, 320, 380, 440, 500, 560, 620, 680};
int xx = 80;
for (int aXt : ellipsePointsXCoordinate) {
POINT_LIST.add(new Point(aXt, xx));
}
for (int i = 0; i < ellipsePointsYCoordinate.length; i++) {
for (int j = i; j < ellipsePointsYCoordinate.length; j++) {
POINT_LIST.add(new Point(ellipsePointsXCoordinate[i], ellipsePointsYCoordinate[j]));
}
}
}
public DrawPanelMain() {
switchPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
switchPanel.setBackground(Color.DARK_GRAY);
switchPanel.add(drawEllipses);
switchPanel.revalidate();
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// first column
c.gridx = 0;
add(switchPanel, c);
// second column
c.gridx = 1;
add(switchPanel, c);
// first row
c.gridy = 0;
// second row
c. gridy = 1;
add(btnPanel, c);
btnPanel.add(new JButton(new AddSwitchAction("Add Switch Panel")));
}
public static void createAndShowGui() {
JFrame frame = new JFrame("RF Connection Panel " + version);
frame.setLayout(new BorderLayout());
frame.add(new DrawPanelMain());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(false);
//frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
/*
* AddSwitchAction will add a new pane to the tabbedPane when the add switch button is clicked
*/
private class AddSwitchAction extends AbstractAction {
public AddSwitchAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String title = "Switch ";
DrawEllipses tabComponent = new DrawEllipses(POINT_LIST);
switchPanel.add(title, tabComponent);
}
}
}
#SuppressWarnings("serial")
class DrawEllipses extends JPanel {
private final int PREF_W = 750; //Window width
private final int PREF_H = 750; //Window height
private final int OVAL_WIDTH = 30;
private static final Color INACTIVE_COLOR = Color.RED;
private static final Color ACTIVE_COLOR = Color.green;
private java.util.List<Point> points;
private java.util.List<Ellipse2D> ellipses = new ArrayList<>();
private Map<Ellipse2D, Color> ellipseColorMap = new HashMap<>();
/*
* This method is used to populate "ellipses" with the initialized ellipse2D dimensions
*/
public DrawEllipses(java.util.List<Point> points) {
this.points = points;
for (Point p : points) {
int x = p.x - OVAL_WIDTH / 2;
int y = p.y - OVAL_WIDTH / 2;
int w = OVAL_WIDTH;
int h = OVAL_WIDTH;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
ellipses.add(ellipse);
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
MyMouseAdapter mListener = new MyMouseAdapter();
addMouseListener(mListener);
addMouseMotionListener(mListener);
}
/*
* paintComponent is used to paint the ellipses
*/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Ellipse2D ellipse : ellipses) {
g2.setColor(ellipseColorMap.get(ellipse));
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
}
/*
* Set the font characteristics, color, and draw the row labels.
*/
g.setFont(new Font("TimesRoman", Font.BOLD, 18));
g.setColor(Color.BLACK);
//Along the top row
g.drawString("External Port", 10, 50);
g.drawString("1", 135, 50);
g.drawString("2", 195, 50);
g.drawString("3", 255, 50);
g.drawString("4", 315, 50);
g.drawString("5", 375, 50);
g.drawString("6", 435, 50);
g.drawString("7", 495, 50);
g.drawString("8", 555, 50);
g.drawString("9", 615, 50);
g.drawString("10", 672, 50);
//Along the Y-axis
g.drawString("Radio 2", 40, 145);
g.drawString("3", 90, 205);
g.drawString("4", 90, 265);
g.drawString("5", 90, 325);
g.drawString("6", 90, 385);
g.drawString("7", 90, 445);
g.drawString("8", 90, 505);
g.drawString("9", 90, 565);
g.drawString("10", 90, 625);
//Along the X-Axis
g.drawString("1", 135, 670);
g.drawString("2", 195, 670);
g.drawString("3", 255, 670);
g.drawString("4", 315, 670);
g.drawString("5", 375, 670);
g.drawString("6", 435, 670);
g.drawString("7", 495, 670);
g.drawString("8", 555, 670);
g.drawString("9", 615, 670);
//Draws a 3DRect around the top row of ellipse2D objects
g2.setColor(Color.lightGray);
g2.draw3DRect(120, 60, 580, 40, true);
g2.draw3DRect(121, 61, 578, 38, true);
g2.draw3DRect(122, 62, 576, 36, true);
}
/*
* MouseAdapter is extended for mousePressed Event that detects if the x, y coordinates
* of a drawn ellipse are clicked. If the color is INACTIVE it is changed to ACTIVE and
* vice versa.
*/
private class MyMouseAdapter extends MouseAdapter {
#Override
/*
* When mousePressed event occurs, the color is toggled between ACTIVE and INACTIVE
*/
public void mousePressed(MouseEvent e) {
Color c;
for (Ellipse2D ellipse : ellipses) {
if (ellipse.contains(e.getPoint())) {
c = (ellipseColorMap.get(ellipse) == INACTIVE_COLOR) ? ACTIVE_COLOR : INACTIVE_COLOR;
ellipseColorMap.put(ellipse, c);
}
}
repaint();
}
}
/*
* This method will set the dimensions of the JFrame equal to the preferred H x W
*/
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
/*
* Used for button click action to change all ellipses to ACTIVE_COLOR
*/
public void activateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, ACTIVE_COLOR);
}
repaint();
}
/*
* Used for button click action to change all ellipses to INACTIVE_COLOR
*/
public void deactivateAll(){
for (Ellipse2D ellipse : ellipses){
ellipseColorMap.put(ellipse, INACTIVE_COLOR);
}
repaint();
}
}

This method will set the dimensions of the JFrame equal to the preferred H x W
No it set the preferred size of the panel. The size of the frame will be the preferred size of all the components added to it plus the frame decorations (title bar, borders).
When I resize the window the Graphics2D objects reduce into a tiny rectangle.
The GridBagLayout respects the preferred size of the component. When there is not enough space to display the component it will shrink to its "minimum size".
You probably need to override the getMinimumSize() method to equal the preferred size. Then in this case the component should just be truncated if space is not available.
If you want you actually painting to shrink then you need to build the logic into your painting code so that the painting is done relative to the space available on the panel.

Try adding your 2D object to a JLabel as BufferedImage of ImageIcon. You can do this by:
JLabel label2 = new JLabel(new ImageIcon(//Location of your Image);
Or I think you can also add Graphics2D objects directly creating them inside label bu I'm not sure about that

Related

How do I repaint after a mouse click in java?

The graphics should repaint with a new color after a mouse click, but they don´t.
I´ve already implemented the MouseListener in the component and in the frame, but in both versions it did´nt work.
The Frame and MouseListener:
public class frame extends Frame
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
String string = new String("1 2 3 4 5 6 7");
final int FRAME_WIDTH = 527;
final int FRAME_HEIGHT = 77;
frame.setAlwaysOnTop(true);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Praxis");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
// JFrame zentriert positionieren; selbst berechnet:
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
frame.setLocation((int) ((d.width)-700), (int) (0));
Font font = new Font("Jokerman", Font.BOLD, 35);
JLabel textLabel = new JLabel(string);
textLabel.setFont(font);
test component = new test();
frame.add(component);
MouseListener listen = new MouseListener()
{
public void mouseClicked(MouseEvent e) {
GlobalVar obj = new GlobalVar();
obj.fillColor1 = obj.farben[1];
component.repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
};
component.addMouseListener(listen);
frame.setVisible(true);
}
}
The File where they get the Color from:
public class GlobalVar{
public static final Color[] farben = new Color[4];{
farben[0] = Color.LIGHT_GRAY;
farben[1] = Color.RED;
farben[2] = Color.GREEN;
farben[3] = Color.PINK;
}
Color fillColor1 = farben[0];
Color fillColor2 = farben[0];
Color fillColor3 = farben[0];
Color fillColor4 = farben[0];
Color fillColor5 = farben[0];
Color fillColor6 = farben[0];
Color fillColor7 = farben[0];
}
The Component which draws the graphics:
public class test extends JComponent
{
GlobalVar obj = new GlobalVar();
#Override
public void paintComponent(Graphics g)
{
if(g instanceof Graphics2D) {
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
// Construct a rectangle and draw it
Rectangle box1 = new Rectangle(2, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box1);
g2.setColor(obj.fillColor1);
g2.fill(box1);
Rectangle box2 = new Rectangle(77, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box2);
g2.setColor(obj.fillColor2);
g2.fill(box2);
Rectangle box3 = new Rectangle(152, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box3);
g2.setColor(obj.fillColor3);
g2.fill(box3);
Rectangle box4 = new Rectangle(227, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box4);
g2.setColor(obj.fillColor4);
g2.fill(box4);
Rectangle box5 = new Rectangle(302, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box5);
g2.setColor(obj.fillColor5);
g2.fill(box5);
Rectangle box6 = new Rectangle(377, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box6);
g2.setColor(obj.fillColor6);
g2.fill(box6);
Rectangle box7 = new Rectangle(452, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box7);
g2.setColor(obj.fillColor7);
g2.fill(box7);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Font f = new Font("Dialog", Font.PLAIN, 30);
g2.setFont(f);
g2.setColor(Color.BLACK);
g2.drawString("1", 30, 48);
g2.drawString("2", 105, 48);
g2.drawString("3", 180, 48);
g2.drawString("4", 255, 48);
g2.drawString("5", 330, 48);
g2.drawString("6", 405, 48);
g2.drawString("7", 480, 48);
}
}
private Color fillColor1;
private Color fillColor2;
private Color fillColor3;
private Color fillColor4;
private Color fillColor5;
private Color fillColor6;
private Color fillColor7;
}
As I said, I expected the graphics to repaint with the first square to be filled with the color red, but the actual result is, that nothing happens when I click on the frame.
Instead of having the test class extending JComponent, I would make it into a JPanel and then put the JPanel on top of the JFrame.
Then I would remove the mouselistener from the JFrame and add it onto the JPanel, by doing this the only command needed to repaint is repaint();.
I believe that this way is more simple and more organized than what you are currently doing.
This should do the trick (note: I made this in netbeans, that is why there is some autogenerated code.):
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
public class Test extends javax.swing.JPanel {
/**
* Creates new form Test
*/
public Test() {
initComponents();
}
GlobalVar obj = new GlobalVar();
#Override
public void paintComponent(Graphics g)
{
if(g instanceof Graphics2D) {
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
// Construct a rectangle and draw it
Rectangle box1 = new Rectangle(2, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box1);
g2.setColor(obj.fillColor1);
g2.fill(box1);
Rectangle box2 = new Rectangle(77, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box2);
g2.setColor(obj.fillColor2);
g2.fill(box2);
Rectangle box3 = new Rectangle(152, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box3);
g2.setColor(obj.fillColor3);
g2.fill(box3);
Rectangle box4 = new Rectangle(227, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box4);
g2.setColor(obj.fillColor4);
g2.fill(box4);
Rectangle box5 = new Rectangle(302, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box5);
g2.setColor(obj.fillColor5);
g2.fill(box5);
Rectangle box6 = new Rectangle(377, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box6);
g2.setColor(obj.fillColor6);
g2.fill(box6);
Rectangle box7 = new Rectangle(452, 2, 71, 71);
g2.setColor(Color.BLACK);
g2.draw(box7);
g2.setColor(obj.fillColor7);
g2.fill(box7);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Font f = new Font("Dialog", Font.PLAIN, 30);
g2.setFont(f);
g2.setColor(Color.BLACK);
g2.drawString("1", 30, 48);
g2.drawString("2", 105, 48);
g2.drawString("3", 180, 48);
g2.drawString("4", 255, 48);
g2.drawString("5", 330, 48);
g2.drawString("6", 405, 48);
g2.drawString("7", 480, 48);
}
}
private Color fillColor1;
private Color fillColor2;
private Color fillColor3;
private Color fillColor4;
private Color fillColor5;
private Color fillColor6;
private Color fillColor7;
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
formMouseClicked(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>
private void formMouseClicked(java.awt.event.MouseEvent evt) {
GlobalVar obj = new GlobalVar();
obj.fillColor1 = obj.farben[1];
repaint();
// TODO add your handling code here:
}
// Variables declaration - do not modify
// End of variables declaration
}

How to add a mouse hover listener to a rectangle in Java

I am trying to make a button using the Rectangle object and am also trying to make the color change on hover, and it will not change.
I have made my code have more generic names for variables that way it would not confuse, here it is:
public class MouseHandler extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if(mx > button.x && mx < button.x+button.width &&
my > button.y && my < button.y+button.height) {
buttonHover = true;
} else {
buttonHover = false;
}
}
}
And I tried calling these lines of code also, but it wouldn't work:
if(buttonHover)
g.setColor(hoverColor);
g.drawRect(button.x, button.y, button.width, button.height);
I will put my full code at the bottom, with the actual variable names. Thanks for the help!
package trivia;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Main extends JFrame{
boolean mainMenu = true;
boolean startHover;
static Color tan = Color.decode("#F4EBC3");
static Color darkGreen = Color.decode("#668284");
static Color buttonColor = Color.decode("#A2896B");
static Color borderColor = Color.decode("#333333");
static Color buttonHover = Color.decode("#F5B66E");
Rectangle header = new Rectangle(0, 0, 500, 100);
Rectangle body = new Rectangle(0, 100, 500, 400);
Rectangle start = new Rectangle(150, 150, 200, 40);
Rectangle howToPlay = new Rectangle(150, 225, 200, 40);
Rectangle quit = new Rectangle(150, 300, 200, 40);
public Main() {
setTitle("Trivia Game!");
setSize(500, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
#Override
public void paint(Graphics g) {
Dimension d = this.getSize();
if(mainMenu = true){
g.setColor(darkGreen);
g.fillRect(header.x, header.y, header.width, header.height);
g.setFont(new Font("Courier", Font.BOLD, 24));
g.setColor(Color.BLACK);
drawCenteredString("Trivia Game!", d.width, 125, g);
g.setColor(tan);
g.fillRect(body.x, body.y, body.width, body.height);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
g.setColor(buttonColor);
g.fillRect(howToPlay.x, howToPlay.y, howToPlay.width, howToPlay.height);
g.setColor(borderColor);
g.drawRect(howToPlay.x, howToPlay.y, howToPlay.width, howToPlay.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("How To Play", d.width, 490, g);
g.setColor(buttonColor);
g.fillRect(quit.x, quit.y, quit.width, quit.height);
g.setColor(borderColor);
g.drawRect(quit.x, quit.y, quit.width, quit.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Quit?", d.width, 640, g);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
if(startHover)
g.setColor(buttonHover);
g.drawRect(start.x, start.y, start.width, start.height);
}
}
public void drawCenteredString(String s, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(s)) / 2;
int y = (fm.getAscent() + (h- (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Main m = new Main();
}
public class MouseHandler extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if(mx > start.x && mx < start.x+start.width &&
my > start.y && my < start.y+start.height) {
startHover = true;
System.out.println("yes");
} else {
startHover = false;
System.out.println("no");
}
}
}
}
I'll start with...
1) If it truly just a rectangle you want to deal with. Please use https://docs.oracle.com/javase/7/docs/api/java/awt/Rectangle.html , Java has been kind enough to make your life simple please don't throw it away. (ignore this keeping here for reference)
2) You should implement MouseMotionListener... I did it for you.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class test extends JFrame implements MouseMotionListener {
boolean mainMenu = true;
boolean startHover;
static Color tan = Color.decode("#F4EBC3");
static Color darkGreen = Color.decode("#668284");
static Color buttonColor = Color.decode("#A2896B");
static Color borderColor = Color.decode("#333333");
static Color buttonHover = Color.decode("#F5B66E");
Rectangle header = new Rectangle(0, 0, 500, 100);
Rectangle body = new Rectangle(0, 100, 500, 400);
Rectangle start = new Rectangle(150, 150, 200, 40);
Rectangle howToPlay = new Rectangle(150, 225, 200, 40);
Rectangle quit = new Rectangle(150, 300, 200, 40);
public test() {
setTitle("Trivia Game!");
setSize(500, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
this.addMouseMotionListener(this);
}
#Override
public void paint(Graphics g) {
Dimension d = this.getSize();
if (mainMenu = true) {
g.setColor(darkGreen);
g.fillRect(header.x, header.y, header.width, header.height);
g.setFont(new Font("Courier", Font.BOLD, 24));
g.setColor(Color.BLACK);
drawCenteredString("Trivia Game!", d.width, 125, g);
g.setColor(tan);
g.fillRect(body.x, body.y, body.width, body.height);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
g.setColor(buttonColor);
g.fillRect(howToPlay.x, howToPlay.y, howToPlay.width,
howToPlay.height);
g.setColor(borderColor);
g.drawRect(howToPlay.x, howToPlay.y, howToPlay.width,
howToPlay.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("How To Play", d.width, 490, g);
g.setColor(buttonColor);
g.fillRect(quit.x, quit.y, quit.width, quit.height);
g.setColor(borderColor);
g.drawRect(quit.x, quit.y, quit.width, quit.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Quit?", d.width, 640, g);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
if (startHover)
g.setColor(buttonHover);
g.drawRect(start.x, start.y, start.width, start.height);
}
}
public void drawCenteredString(String s, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(s)) / 2;
int y = (fm.getAscent() + (h - (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
test m = new test();
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("lol");
int mx = e.getX();
int my = e.getY();
if (mx > start.x && mx < start.x + start.width && my > start.y
&& my < start.y + start.height) {
startHover = true;
System.out.println("yes");
} else {
startHover = false;
System.out.println("no");
}
}
}
If you read below you can see there are a lot of things wrong with your code. Don't let that scare you from learning. Do it step by step and you will be fine.
You've several issues going on here:
You're doing drawing directly within a JFrame, a dangerous thing to do, since JFrames hold many components, several I'm sure that you're not familiar with, including borders, rootpane, glasspane, and contentpane, and if you mess up painting, it can mess up the drawing of these critical components.
Also by painting inside of a paint method, you loose all the advantages of Swing graphics.
Also you appear to have most of your program design and logic within a painting method, something that you should never do since you don't have full control over when or even if that method gets called.
Instead, you should create your button component in its own class, separate from the JFrame
Give your class ability to be placed in a JPanel
And give it a rollover capability.
For my money though, I'd just extend a JButton or better, just use a JButton, and make it look the way I want rather than trying to re-invent the wheel.
e.g.,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class Main2 extends JPanel {
private static final Color TAN = Color.decode("#F4EBC3");
private static final Color DARK_GREEN = Color.decode("#668284");
private static final Color BUTTON_COLOR = Color.decode("#A2896B");
private static final Color BORDER_COLOR = Color.decode("#333333");
private static final Color BUTTON_ROLLOVER_COLOR = Color.decode("#F5B66E");
private static final String TITLE = "Trivia Game!";
private static final Font TITLE_FONT = new Font("Courier", Font.BOLD, 24);
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W - 30;
private JButton startButton;
private JButton howToPlayButton;
private JButton quitButton;
public Main2() {
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(TITLE_FONT);
int blGap = 15;
titleLabel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap, blGap));
JPanel titlePanel = new JPanel(new GridBagLayout());
titlePanel.setBackground(DARK_GREEN);
titlePanel.add(titleLabel);
JPanel centerInnerPanel = new JPanel(new GridLayout(0, 1, blGap, 2 * blGap));
centerInnerPanel.setOpaque(false);
centerInnerPanel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap, blGap));
centerInnerPanel.add(startButton = createButton("Start"));
centerInnerPanel.add(howToPlayButton = createButton("How To Play"));
centerInnerPanel.add(quitButton = createButton("Quit?"));
JPanel centerOuterPanel = new JPanel(new GridBagLayout());
centerOuterPanel.setBackground(TAN);
centerOuterPanel.add(centerInnerPanel);
setLayout(new BorderLayout());
add(titlePanel, BorderLayout.PAGE_START);
add(centerOuterPanel, BorderLayout.CENTER);
}
private JButton createButton(String name) {
final JButton button = new JButton(name);
button.setFont(TITLE_FONT.deriveFont(20F));
button.setBackground(BUTTON_COLOR);
Border emptyBorder = BorderFactory.createEmptyBorder(5, 25, 5, 25);
Border lineBorder = BorderFactory.createLineBorder(BORDER_COLOR);
Border nestedBorder = BorderFactory.createCompoundBorder(lineBorder, emptyBorder);
button.setBorder(nestedBorder);
button.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel)e.getSource();
if (model.isRollover()) {
button.setBackground(BUTTON_ROLLOVER_COLOR);
} else {
button.setBackground(BUTTON_COLOR);
}
}
});
return button;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
int w = Math.max(super.getPreferredSize().width, PREF_W);
int h = Math.max(super.getPreferredSize().height, PREF_H);
return new Dimension(w, h);
}
private static void createAndShowGui() {
Main2 mainPanel = new Main2();
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_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();
}
});
}
}

How do you add graphics to a different panel in Java

import java.awt.event.ActionEvent; //this is my button class
import java.awt.event.ActionListener;
import javax.swing.*;
import java.awt.*;
import java.awt.Color;
import java.awt.Dimension;
public class Buttons extends JFrame{
private JPanel panel1, panel2;
private JButton button1, button2, button3;
private JMenuBar menuBar;
public Buttons()
{
createPanel();
addPanel();
}
private void createPanel()
{
setLocationRelativeTo(null);
panel1 = new JPanel();
panel1.setBackground(Color.cyan);
button1 = new JButton("Start");
button1.addActionListener(new addButtonListener());
button1.setBounds(50, 90, 190, 30);
button2 = new JButton("Instructions");
button2.setBounds(70, 130, 160, 30);
panel2 = new JPanel();
//button3 = new JButton("Test");
//panel2.setBackground(Color.orange);
//button3.setBounds(50, 50, 90, 30);
}
private void addPanel()
{
panel1.add(button1);
panel1.add(button2);
panel2.add(button3);
add(panel1);
}
class addButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
getContentPane().removeAll();
getContentPane().add(panel2);
repaint();
printAll(getGraphics());
}
}
public static void main(String[]args)
{
JMenuItem exitAction = new JMenuItem("Exit");
JMenuBar menuBar = new JMenuBar();
JMenu save = new JMenu("Save");
JMenu file = new JMenu("File");
JMenu credit = new JMenu("Credit");
file.add(exitAction);
menuBar.add(file);
menuBar.add(save);
menuBar.add(credit);
exitAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
Buttons frame = new Buttons();
frame.setTitle("Bikini Bottom Marathon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,500);
frame.setVisible(true);
frame.setJMenuBar(menuBar);
}
}
import javax.swing.*;
//this is my graphics class to create a board. the images are imported from saved
pictures in my class file. I'm trying to add the output from this code (the board)
onto the buttons class
import java.applet.*;
import java.awt.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;
import java.awt.image.*;
import java.applet.*;
public class compscigame extends Applet
{
public void paint (Graphics page)
{
Image pineapple = getImage(getCodeBase(), "pineapple.jpg");
page.drawImage (pineapple, 50, 500, 50, 50, this);
Image raygun = getImage(getCodeBase(), "Raygun.jpg");
page.drawImage (raygun, 300, 350, 50, 50, this);
Image karen = getImage(getCodeBase(), "Karen.jpg");
page.drawImage(karen, 100, 50, 50, 50, this);
Image karensmad = getImage(getCodeBase(), "karensmad.jpg");
page.drawImage(karensmad, 150, 400, 50, 50, this);
Image rocketboots = getImage(getCodeBase(), "rocketboots.jpg");
page.drawImage(rocketboots, 200, 300, 50, 50, this);
Image emptybeaker = getImage(getCodeBase(), "emptybeaker.jpg");
page.drawImage(emptybeaker, 350, 150, 50, 50, this);
Image happykaren = getImage(getCodeBase(), "happykaren.jpg");
page.drawImage(happykaren, 100, 50, 50, 50, this);
Image raygunnotshooting = getImage(getCodeBase(), "raygunnotshooting.jpg");
page.drawImage (raygunnotshooting, 450, 200, 50, 50, this);
Image notfirerocket = getImage(getCodeBase(), "notfirerocket.jpg");
page.drawImage (notfirerocket, 450, 450, 50, 50, this);
Image firerocket = getImage(getCodeBase(), "firerocket.jpg");
page.drawImage (firerocket, 500, 200, 50, 50, this);
Image fullbeaker = getImage(getCodeBase(), "fullbeaker.jpg");
page.drawImage (fullbeaker, 250, 250, 50, 50, this);
Image boots = getImage(getCodeBase(), "boots.jpg");
page.drawImage (boots, 300, 500, 50, 50, this);
Image krustykrab = getImage(getCodeBase(), "krustykrab.jpg");
page.drawImage(krustykrab, 50, 50, 50, 50, this);
Board board = new Board(page, new Color (255,0,100));
setBackground(Color.YELLOW);
}
class Board
{
private Graphics g;
private Color col;
private Square [][] squares;
public Board (Graphics g, Color col)
{
this.col = col;
this.g = g;
Color temp;
squares = new Square[10][10];
for (int i = 1; i <= 10; i++)
{
for (int j = 1; j <= 10; j++)
{
int num;
if (i + j % 2 == 0)
temp = col;
else
temp = new Color(255, 0 , 255);
Square t;
t = new Square (g, temp, i, j);
if (j % 2 != 0)
{
num = 10 - i + 1 + 10 * (j - 1);
}
else
{
num = i + 10 * (j - 1);
}
t.setVal(num);
t.drawSquare();
squares[i - 1][j - 1] = t;
}
}
}
}
class Square
{
private Color col;
private int x;
private int y;
private Graphics g;
private int val;
public Square (Graphics g, Color col, int x, int y)
{
this.col = col;
this.g = g;
this.x = x;
this.y = y;
val = 0;
}
public void setVal(int num)
{
val = num;
}
public void drawSquare()
{
g.setColor(col);
g.drawRect(50 + (10 - x) * 50, 50 + (10 - y) * 50, 50, 50);
String str = "" + val;
g.drawString(str, 50 + (10 - x) * 50 + 5, 50 + (10 - y) * 50 + 10);
}
}
I just want the board to be in another panel. As you can see I used ActionListener to create the action my buttons will do. When you click Start it takes you to the button that says "test." I want the graphic from the Board to show on this second panel, (panel2)
}
Make a custom inner class that extends JPanel and then override the onPaintComponent method. Draw the Board there. Create a new BoardPanel instead of a JPanel.
Put your paint code in a seperate class (JPanel)
public void paint (Graphics page)
{
...
}
There is no need for the applet to have a dependency on any of this code.

JTabbedPanel and Paint

I have small issue. In main i have such thing:
JTabbedPane tabsPane = new JTabbedPane();
add(tabsPane,BorderLayout.CENTER);
JPanel tab1Panel = new JPanel();
JPanel tab2Panel = new JPanel();
//DrawingWindow drawingWindow= new DrawingWindow();
//add(drawingWindow);
tabsPane.addTab("Animacja", tab1Panel);
tabsPane.addTab("Wykresy", tab2Panel);
JButton test = new JButton("Press");
tab2Panel.add(test);
Drawing Window class
public class DrawingWindow extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public static Balls balls=new Balls();
public DrawingWindow() {
MakeBall();
}
private void MakeBall()
{
balls=new Balls(10,205,5,10);
}
public void paint(Graphics gg){
super.paint(gg);
Graphics2D g = (Graphics2D) gg;
g.setColor(Color.GRAY);
g.fillRect(0,70,515,410);
g.setColor(Color.WHITE);
g.drawLine(10, 285, 57, 265);
g.drawLine(10, 285, 57, 305);
g.drawLine(515, 285, 458, 265);
g.drawLine(515, 285, 458, 305);
for(int ii=0;ii<Parameters.numberOfCovers;ii++)
{
if(Parameters.whatCovers[ii]==0)
{
g.setColor(Color.YELLOW);
g.fillRect(132+(57*2*ii), 205, 29+2*Parameters.cmCovers[ii], 150 );
}
if(Parameters.whatCovers[ii]==1)
{
g.setColor(Color.GREEN);
g.fillRect(132+(57*2*ii), 205, 29+2*Parameters.cmCovers[ii], 150 );
}
// Ellipse2D.Double shape = new Ellipse2D.Double(balls.getX(), balls.getY(), balls.getVelocity(),balls.getRadius());
// g.fill(shape);
repaint();
}
}
public void funkcja()
{
repaint();
}
}
And my question is after uncommenting the // in Main my JTabbedPanel disappears.
I want paint to draw in JTab.
http://forum.4programmers.net/Java/232952-jtabbedpanel_i_paint?mode=download&id=6326 <-- While it is commented
http://forum.4programmers.net/Java/232952-jtabbedpanel_i_paint?mode=download&id=6327 <-- After uncommenting.
Iam kinda newbie in Java so I would like to get easy answers :P.
Hej,
replace this
JPanel tab1Panel = new JPanel();
with that
JPanel tab1Panel = new DrawingWindow();
up to now, you add the DrawingPanel to another JPanel, but if you want to draw on your Tab, then add create a JPanel, which you'll add to your JTabbedPane with addTab().

Custom component not visible initially, but then becomes visible

I've come across an issue when messing around with shapes.
I created a simple program with a slider with which you manipulate the size of an arc. The problem is that when I run it, the arc isn't painted to the screen. However, when I change the value of the slider, everything starts working perfectly. Any thoughts on what this might be caused by? Here's the code:
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.awt.*;
import java.awt.geom.*;
#SuppressWarnings("serial")
public class GraphicsTest2 extends JFrame implements ChangeListener { // START OF GraphicsTest2
private JPanel sliderPanel, thePanel;
private JSlider slider;
private DrawStuff draw;
public static void main(String[] args) { // START OF main
new GraphicsTest2();
} // END OF main
public GraphicsTest2() { // START OF CONSTRUCTOR
super("Graphics test 2");
this.setSize(500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thePanel = new JPanel();
thePanel.setLayout(new BorderLayout(10, 10));
slider = new JSlider(JSlider.HORIZONTAL, 1, 360, 120);
slider.addChangeListener(this);
sliderPanel = new JPanel();
sliderPanel.add(slider, BorderLayout.CENTER);
draw = new DrawStuff();
thePanel.add(sliderPanel, BorderLayout.SOUTH);
thePanel.add(draw, BorderLayout.CENTER);
this.add(thePanel, BorderLayout.CENTER);
this.pack();
this.validate();
this.setVisible(true);
} // END OF CONSTRUCTOR
public void stateChanged(ChangeEvent e) { // START OF stateChanged
if(e.getSource() == slider) {
int size = slider.getValue();
draw.arc = new Arc2D.Double(draw.getWidth() / 2 - 50, draw.getHeight() / 2 - 50, 100, 100, 0, size, Arc2D.PIE);
this.repaint();
}
} // END OF stateChanged
private class DrawStuff extends JComponent { // START OF DrawStuff
Shape arc;
public void paintComponent(Graphics g) { // START OF paintComponent
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.GREEN);
g2.fill(arc);
} // END OF paintComponent
public DrawStuff() {
this.setPreferredSize(new Dimension(100, 140));
arc = new Arc2D.Double(this.getWidth() / 2 - 50, this.getHeight() / 2 - 50, 100, 100, 0, 120, Arc2D.PIE);
}
} // END OF DrawStuff
} // END OF GraphicsTest2
When you create your arc in the constructor of DrawStuff here:
arc = new Arc2D.Double(this.getWidth() / 2 - 50, this.getHeight() / 2 - 50, 100, 100, 0, 120, Arc2D.PIE);
this.getWidth() and this.getHeight() will give a result of 0 because the components are not sized yet. A simple fix would be to use the fixed size like this:
arc = new Arc2D.Double(210 / 2 - 50, 140 / 2 - 50, 100, 100, 0, 120, Arc2D.PIE);

Categories

Resources