I know there have been many topics on this subject before and I have used Google extensively to figure this out, but whatever I do I cannot get two panels to display in one JFrame. I have tried many things including CardLayout but that didn't seem to work. I have a feeling this is a very easy solution..
The purpose is to see the difference between the two panels due to the random positioning.
Here are some of the java files (only pertinent code - there is also a Snowman.java but it just provides the drawing for the snowmen similar to ghost.java):
Ghost.java
import java.awt.*;
public class Ghost
{
private int x, y;
private String name;
private boolean happy;
private Color color;
public Ghost (Color shade, int upperX, int upperY, String a, boolean b)
{
color = shade;
x = upperX;
y = upperY;
name = a;
happy = b;
}
public void draw (Graphics page)
{
page.setColor(color);
page.fillOval (x, y, 50, 125);
page.fillRect (x+1, y+60, 49, 75); // body of ghost
page.setColor(Color.black);
page.fillOval (x+12, y+10, 8, 8);
page.fillOval (x+32, y+10, 8, 8); // eyes
page.setColor(Color.white);
page.drawString(name, x+8, y-5); // name
page.setColor(Color.black);
if (happy == true)
page.fillArc (x+10, y+30, 33, 10, 180, 180);
else
page.fillArc (x+10, y+30, 33, 10, 0, 180); // smile/frown
}
public void setColor (Color shade)
{
color = shade;
}
public void setX (int upperX)
{
x = upperX;
}
public void setY (int upperY)
{
y = upperY;
}
HalloweenPanel.java :
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class HalloweenPanel extends JPanel
{
private Ghost ghost1, ghost2, ghost3;
private Snowman snowman1, snowman2;
public HalloweenPanel()
{
setBackground (Color.black);
Random rand = new Random();
int randomX = rand.nextInt(700)+50;
int randomY = rand.nextInt(400)+50;
boolean randomHappy = (Math.random() < 0.5);
boolean randomHappy2 = (Math.random() < 0.5);
ghost1 = new Ghost (Color.white, randomX, randomY, "Scary", randomHappy2);
ghost2 = new Ghost (Color.blue, randomX, 100, "Happy", true);
ghost3 = new Ghost (Color.yellow, 300, randomY, "Scared", randomHappy);
snowman1 = new Snowman (500, 50);
snowman2 = new Snowman (750, 100);
}
public void paintComponent (Graphics page)
{
Random rand = new Random();
int randomX2 = rand.nextInt(900);
int randomY2 = rand.nextInt(500);
super.paintComponent(page);
ghost2.setX(randomX2);
ghost3.setY(randomY2);
ghost1.draw(page);
ghost2.draw(page);
ghost3.draw(page);
snowman1.draw(page);
snowman2.draw(page);
}
}
HalloweenDriver.java:
import javax.swing.*;
import java.awt.*;
public class HalloweenDriver
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Halloween - Winter is Coming..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
HalloweenPanel panel = new HalloweenPanel();
HalloweenPanel panel2 = new HalloweenPanel();
mainPanel.setLayout(new GridLayout(1,0));
mainPanel.add(panel);
mainPanel.add(panel2);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
}
frame.getContentPane().add(panel);
frame.getContentPane().add(panel2);
You are trying to add two panels to the CENTER of a BorderLayout. This can't be done.
Try:
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(panel2, BorderLayout.SOUTH);
to see the difference.
If this isn't what you want then try another layout manager. Read the Swing tutorial on Layout Managers.
Or, if you are trying to stack the two panels on top of one another (on the Z axis) then try the OverlayLayout. This is not covered in the tutorial so you will need to look at the API. You will also need to make the "top" panel non-opaque() so it doesn't paint over top of the bottom panel.
Related
This question already has answers here:
paintComponent not painting onto JPanel
(2 answers)
Closed 5 years ago.
I'm making a game in Java and first I didn't use a JPanel which caused flickering on repaint() and so I decided to use it. I'm not sure how to implement it in my current code. When I tried to do so all I got was a window that was as small as it gets. My original Window class code:
public class Window extends JFrame {
private double stepLen;
public Window(double stepLen) {
this.stepLen = stepLen;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
this.setLayout(null);
getContentPane().setBackground(Color.black);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int x = (dim.width - this.getSize().width)/2;
int y = (dim.height - this.getSize().height)/2;
this.setLocation(x, y);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
add(goal);
goal.setBounds(325, -10, 600, 50);
setFocusable(true);
requestFocusInWindow();
this.setVisible(true);
}
This code works and it creates a window.
Main class:
Window window = new Window(50);
And then I tried to do it this way:
I have separate GameFrame (JFrame) and GameCanvas (JPanel) classes.
The Frame looks like this:
public class GameFrame extends JFrame{
private double stepLen;
public GameFrame() {
this.stepLen = 50;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
this.setLayout(null);
this.setVisible(true);
this.getContentPane().setBackground(Color.black);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int x = (dim.width - this.getSize().width)/2;
int y = (dim.height - this.getSize().height)/2;
GameCanvas gcanvas = new GameCanvas();
this.add(gcanvas);
this.pack();
this.setLocation(x, y);
}
}
}
And the GameCanvas class
public class GameCanvas extends JPanel {
public GameCanvas() {
setDoubleBuffered(true);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
this.add(goal);
goal.setBounds(325, -10, 600, 50);
this.getPreferredSize();
this.setVisible(true);
this.repaint();
}
Camickr is correct - go up vote and mark his answer as correct, this is only here to save him from pulling out what little hair he has remaining
You're using a null layout, without taking over its responsibility
Failed to provide sizing hints to for the component to allow the layout manager (which you're no longer using) to do it's job
This are all common mistakes, to which there are countless answers already provided
GameFrame
public class GameFrame extends JFrame {
private double stepLen;
public GameFrame() {
this.stepLen = 50;
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Frogger");
// Well, there's your problem...
//this.setLayout(null);
// Don't do this here...
this.setVisible(true);
this.getContentPane().setBackground(Color.black);
// Simpler way to achieve this
//Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
//int x = (dim.width - this.getSize().width) / 2;
//int y = (dim.height - this.getSize().height) / 2;
GameCanvas gcanvas = new GameCanvas();
this.add(gcanvas);
this.pack();
//this.setLocation(x, y);
setLocationRelativeTo(null);
setVisible(true);
}
}
GameCanvas
public class GameCanvas extends JPanel {
public GameCanvas() {
// Pointless
//setDoubleBuffered(true);
JLabel goal = new JLabel();
goal.setText("|=========|");
goal.setForeground(Color.WHITE);
goal.setFont(new Font("Seif", Font.PLAIN, 20));
this.add(goal);
// Pointless
//goal.setBounds(325, -10, 600, 50);
// Pointless
//this.getPreferredSize();
// Pointless
//this.setVisible(true);
// Pointless
//this.repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paintComponent(Graphics g) {
int firstRoad = 5;
int i = 0;
int max = 10;
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(Color.WHITE);
g2.drawRect(5, 30, 75, 40);
while (i < max) {
g2.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(3));
if (i % 2 == 0) {
g.setColor(Color.WHITE);
g.drawRect(3, firstRoad + 50 * i, 793, 50);
//g.fillRect(3, firstRoad + 50 * i, 793, 50);
} else {
g2.setColor(Color.WHITE);
g2.drawRect(3, firstRoad + 50 * i, 793, 50);
}
i++;
}
}
}
So, the way I was taught in my AP Computer Science class is to set your frame size and other frame characteristics in your main. Here is an example:
import javax.swing.JFrame;
public class theSetupClass{
public static void main(String[] args){
JFrame theGUI = new JFrame();
theGUI.setSize(300,400); //Sets the frame size to 300 by 400
theGUI.setTitle("Example");
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theComponentClass component = new theComponentClass(); //Create new theComponentClass
frame.add(component);//Add theComponentClass to theGUI
frame.setVisible(true);
}
}
The code above creates the JFrame and adds the following class to it.
import java.awt.*;
import javax.swing.*;
public class theComponentClass extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Rectangle r = new Rectangle(10,10,this.getWidth()-10,this.getHeight()-10);
//Creates a rectangle that is 10 pixels away from all sides of the frame
g2.fill(r); //Draws and fills the rectangle
}
}
I hope that you find this helpful!
So i made a simple graphic GUI where the rigth part is a JScrollPane with a JPanel (canvas) inside (mainGUI class). When I try to draw some box (using Box class) and run it, when scrolling i get this repeating windowsXP graphic error, where the boxes kind of render too slow or something, kind of dificult to explain. How can I get an uniform non-glitching drawing after scrolling? Is there a rendering option or something?
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Grafin{
public static void main(String args[]){
mainGUI gui = new mainGUI();
}
}
class mainGUI{
private JFrame mainFrame;
private JPanel toolsPanel;
private JPanel canvasPanel;
public mainGUI(){
try{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
}catch(Exception e){
System.out.println(e.getMessage());
}
mainFrame = new JFrame("Grafin | untitled");
mainFrame.setLayout(new GridBagLayout());
mainFrame.setSize(920, 580);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
loadGUI();
}
public void loadGUI(){
GridBagConstraints c = new GridBagConstraints();
//toolsPanel (izq) y canvasPanel (der) dentro de mainFrame
toolsPanel = new JPanel(new GridBagLayout());
toolsPanel.setPreferredSize(new Dimension(250,580));
c.gridx = 0;
c.gridy = 0;
c.weightx = 0.1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
mainFrame.add(toolsPanel, c);
canvasPanel = new JPanel(new GridBagLayout());
canvasPanel.setBackground(Color.white);
canvasPanel.setPreferredSize(new Dimension(1500,1000));
JScrollPane canvasScroll = new JScrollPane(canvasPanel);
canvasScroll.setPreferredSize(new Dimension(670,580));
c.gridx = 1;
c.gridy = 0;
c.weightx = 0.9;
mainFrame.add(canvasScroll, c);
canvasScroll.setSize(canvasScroll.getPreferredSize());
canvasScroll.setBackground(Color.white);
//CanvasPanel:
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
Box b1 = new Box(10, 200, 30, 128);
Box b2 = new Box(200, 10, 120, 40);
canvasPanel.add(b1, c);
canvasPanel.add(b2, c);
mainFrame.pack();
}
}
class Box extends JPanel{
private Color borderColor;
private Color fillColor;
public int x;
public int y;
public int width;
public int height;
public Box(){
borderColor = Color.black;
fillColor = new Color(242, 242, 242);
x = y = 1;
width = height = 30;
}
public Box(int px, int py, int w, int h){
x = px;
y = py;
borderColor = Color.black;
fillColor = new Color(242, 242, 242);
width = w;
height = h;
}
public void changeFillColor(Color c){
fillColor = c;
}
public void changeBorderColor(Color c){
borderColor = c;
}
public void paint(Graphics g){
g.setColor(fillColor);
g.fillRect(x, y, width, height);
g.setColor(borderColor);
g.drawRect(x, y, width, height);
}
}
Thanks in advance
Happy holidays
First and foremost, you're overriding the wrong painting method. You should not be overriding JPanel's paint method but rather its paintComponent method, since this is a more specific painting method and has double buffering by default, a plus when doing animation (which you're kind of doing with your scrolling).
Even more important is that you're not calling the super's painting method within your override, super.paintComponent(g) if overriding paintComponent, or super.paint(g) if (incorrectly) overriding paint. This prevents your JPanel from cleaning dirty pixels.
Other issues: You're adding two components to a GridBagLayout-using component, but are using the very same GridBagConstraints for both, something that you shouldn't be doing.
Also, your Box class should be a logical class and not a component class. In other words, it shouldn't extend any Swing GUI component, and should be drawn within the canvasPanel.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Grafin2 extends JPanel {
private static final int PREF_W = 920;
private static final int PREF_H = 580;
private static final Dimension TOOLS_SIZE = new Dimension(250, PREF_H);
private static final Dimension CANVAS_SIZE = new Dimension(1500, 1000);
private JPanel toolsPanel = new JPanel();
private CanvasPanel canvasPanel = new CanvasPanel();
public Grafin2() {
MyBox box1 = new MyBox(10, 200, 30, 128);
MyBox box2 = new MyBox(200, 10, 120, 40);
box1.changeFillColor(new Color(255, 120, 120));
box2.changeFillColor(new Color(220, 220, 255));
canvasPanel.addMyBox(box1);
canvasPanel.addMyBox(box2);
toolsPanel.setPreferredSize(TOOLS_SIZE);
canvasPanel.setBackground(Color.white);
canvasPanel.setPreferredSize(CANVAS_SIZE);
JScrollPane canvasScroll = new JScrollPane(canvasPanel);
setLayout(new BorderLayout());
add(toolsPanel, BorderLayout.LINE_START);
add(canvasScroll, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class CanvasPanel extends JPanel {
// a collection to hold all the boxes
private List<MyBox> boxes = new ArrayList<>();
public void addMyBox(MyBox myBox) {
boxes.add(myBox);
}
#Override // again, this is the proper painting method
protected void paintComponent(Graphics g) {
super.paintComponent(g); // never forget this!
for (MyBox myBox : boxes) {
myBox.draw(g); // draw all the boxes that we hold
}
}
}
private static void createAndShowGui() {
Grafin2 mainPanel = new Grafin2();
JFrame frame = new JFrame("Grafin2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
// this is a logical class, **not** a component class.
class MyBox {
private Color borderColor;
private Color fillColor;
public int x;
public int y;
public int width;
public int height;
public MyBox() {
borderColor = Color.black;
fillColor = new Color(242, 242, 242);
x = y = 1;
width = height = 30;
}
public MyBox(int px, int py, int w, int h) {
x = px;
y = py;
borderColor = Color.black;
fillColor = new Color(242, 242, 242);
width = w;
height = h;
}
public void changeFillColor(Color c) {
fillColor = c;
}
public void changeBorderColor(Color c) {
borderColor = c;
}
public void draw(Graphics g) {
// no need to call a super method
// because there is none for this class
g.setColor(fillColor);
g.fillRect(x, y, width, height);
g.setColor(borderColor);
g.drawRect(x, y, width, height);
}
}
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
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have written a program that paints 5 pictures onto a canvas in jframe.
I have now added a jtextfield so that the user can input a number using an actionlistener.
Ideally, the number that the user enters should then produce that amount of pictures on a new canvas.
problem is, i cant remove the canvas object and add a new canvas with the new amount of pictures on it.
please help
public class TaxiFrame extends JFrame implements ActionListener {
private JLabel L1 = new JLabel("Number of Taxis:");
private JLabel L2 = new JLabel("Type an integer and press enter");
private JTextField t1 = new JTextField (" ");
public TaxiFrame() {
super("This is the Frame");
setSize(600, 400);
getContentPane().setBackground(Color.CYAN);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout(10, 10));
Random rx = new Random();
Random ry = new Random();
for(int i = 0; i < 5; i ++)
{
TaxiCanvas tax = new TaxiCanvas();
tax.setBounds(rx.nextInt(600 - 100), ry.nextInt(400 - 100), 100, 100);
add(tax);
}
JPanel p = new JPanel();
p.setOpaque(false);
p.add(L1);
getContentPane().
add("South", p);
p.setOpaque(false);
p.add(t1);
getContentPane().
add("South", p);
p.setOpaque(false);
p.add(L2);
getContentPane().
add("South", p);
setVisible(true);
t1.addActionListener(this);
}
public static void main(String[] args) {
new TaxiFrame();
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == t1)
{
if(Integer.parseInt(t1.getText()) > 0)
{
getContentPane().removeAll();
TaxiCanvas tax = new TaxiCanvas();
add(tax);
}
}
}
}
thanks alot
taxi canvas code is
import java.awt.*;
import javax.swing.*;
public class TaxiCanvas extends JComponent
{
private Taxi taxi = new Taxi();
public void paint(Graphics g)
{
taxi.paint(g);
}
}
taxi code
import java.awt.*;
public class Taxi
{
public void paint(Graphics g)
{
// drawing the car body
g.setColor(Color.yellow);
g.fillRect(0,10, 60, 15);
// drawing the wheels
g.setColor(Color.black);
g.fillOval(10, 20, 12, 12); // left wheel
g.fillOval(40, 20, 12, 12); // right wheel
int x[] = {10, 20, 40, 50}; // coordinate arrays for the
int y[] = {10, 0, 0, 10}; // car cabin
g.setColor(Color.yellow);
g.fillPolygon(x, y, 4); // drawing the cabin in yellow
g.setColor(Color.black);
g.drawString("20", 25, 22);
g.drawLine(0, 25, 60, 25);
}
}
When removing and adding components you need to revalidate() and repaint()
Instead of adding and removing containers consider using a CardLayout that will "layer" your containers and let you navigate through them. See How to use CardLayout
Don't override the paint method of JComponent. instead override paintComponent and make sure to call super.paintComponent as not to break the paint chain and probably leaving you with paint artifacts.
Dont use this deprecated add("South", p); method. Instead use add(p, BorderLayout.SOUTH)
Trying to tax.setBounds will do nothing, as far as placement, as your layout is set (not null)
You are trying to add to "South" a bunch of times. Each position can only hold one component
When adding to BorderLayout, if you don't specify a position when adding, it will automatically get added to the CENTER. So if you try to add multiple components without specify a position, only the last component you add will be shown.
Swing apps should be run on the Event Dispatch Thread (EDT). You can do so by wrapping your code in your main in a SwingUtilities.invokeLater.... See more at Initial Threads
Honestly I have no idea what your code is attempting to do, but look at RadioDef's comment below, see if it means anything to you.
If you want to add multiple Taxi objects to your TaxiCanvas, see this answer where you can use a List of Taxi objects and iterate through them in the paintComponent method.
I implemented many of the suggestions by #peeskillet as well as cleaned up the code a little and here is the result.
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
public class TaxiFrame
extends JFrame
implements ActionListener {
private JLabel label1 = new JLabel("Number of Taxis:");
private JLabel label2 = new JLabel("Type an integer and press enter");
private JTextField inputField = new JTextField(10);
private JPanel taxiPanel = new JPanel();
private Dimension tpSize = new Dimension(600, 400);
private Random rand = new Random();
public TaxiFrame() {
super("This is the Frame");
getContentPane().setBackground(Color.CYAN);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout(10, 10));
taxiPanel.setLayout(null);
taxiPanel.setOpaque(false);
taxiPanel.setPreferredSize(tpSize);
add(taxiPanel, BorderLayout.CENTER);
JPanel p = new JPanel();
p.setOpaque(false);
p.add(label1);
p.add(inputField);
p.add(label2);
add(p, BorderLayout.SOUTH);
inputField.addActionListener(this);
inputField.setText("5");
addNewTaxis(5);
pack();
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
private void addNewTaxis(int numTaxis) {
for(int i = 0; i < numTaxis; i++) {
addNewTaxi();
}
}
private void addNewTaxi() {
TaxiCanvas tc = new TaxiCanvas();
tc.setBounds(
rand.nextInt(tpSize.width - 100),
rand.nextInt(tpSize.height - 100),
100, 100
);
taxiPanel.add(tc);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == inputField) {
int numTaxis = Integer.parseInt(inputField.getText());
if(numTaxis > 0) {
taxiPanel.removeAll();
addNewTaxis(numTaxis);
taxiPanel.revalidate();
repaint();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TaxiFrame();
}
});
}
public static class TaxiCanvas
extends JComponent {
private Taxi taxi = new Taxi();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
taxi.paint(g);
}
}
public static class Taxi {
public void paint(Graphics g) {
// drawing the car body
g.setColor(Color.yellow);
g.fillRect(0,10, 60, 15);
// drawing the wheels
g.setColor(Color.black);
g.fillOval(10, 20, 12, 12); // left wheel
g.fillOval(40, 20, 12, 12); // right wheel
int x[] = {10, 20, 40, 50}; // coordinate arrays for the
int y[] = {10, 0, 0, 10}; // car cabin
g.setColor(Color.yellow);
g.fillPolygon(x, y, 4); // drawing the cabin in yellow
g.setColor(Color.black);
g.drawString("20", 25, 22);
g.drawLine(0, 25, 60, 25);
}
}
}
Please don't accept this answer, I just wanted to show they were good suggestions and show the working code. There were many small Swing-related bugs but otherwise the code works.
I am trying to paint colored rectangles of equal width under a JSlider such that the tick marks separate colors. I am really close but cannot get it quite perfect. I have printed out a bunch of values and my issue is the slider's width is not the actual length of the sliding bar. The x position of the slider is not the starting place of the bar either. Here is my code setting my Colored Rectangles bounds in terms of the sliders position.
for(int i = 0; i < Global.emSpectrum.length; i++) //emSpectrum.length is the number of colored rectangles
{
emSpectrum.get(i).setColorRect(Global.emSpectrum[i], 13 + i * (int)((this.slider.getWidth())/Global.emSpectrum.length), //13 lines up the first color under the bar
this.slider.getY() + this.slider.getHeight()/2, (int)((this.slider.getWidth())/Global.emSpectrum.length),
(int)(Global.rectHeight * getHeight()));
}
Is there just a better way to go about this?
Thanks!
Yep, a decent solution is to use a Dictionary such as a HashTable<Integer, JLabel> and fill it with JLabels that hold ImageIcons of your color rectangles, using an Integer that corresponds with the appropriate location on the JSlider. For example, my SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.swing.*;
public class SliderEg extends JPanel {
public static final Color[] COLORS = { Color.red, Color.orange,
Color.yellow, Color.green, Color.blue, Color.cyan};
private static final int BI_W = 30;
private static final int BI_H = 10;
private JSlider slider = new JSlider(0, 100, 0);
public SliderEg() {
int majorSpacing = slider.getMaximum() / (COLORS.length - 1);
Dictionary<Integer, JLabel> dictionary = new Hashtable<Integer, JLabel>();
slider.setMajorTickSpacing(majorSpacing);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setSnapToTicks(true);
for (int i = 0; i < COLORS.length; i++) {
ImageIcon icon = createColorIcon(COLORS[i]);
JLabel label = new JLabel(icon);
int key = i * majorSpacing;
dictionary.put(key, label);
}
slider.setLabelTable(dictionary);
setLayout(new BorderLayout());
add(slider, BorderLayout.CENTER);
}
private ImageIcon createColorIcon(Color color) {
BufferedImage img = new BufferedImage(BI_W, BI_H,
BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(color);
g.fillRect(0, 0, BI_W, BI_H);
g.dispose();
return new ImageIcon(img);
}
private static void createAndShowGui() {
SliderEg mainPanel = new SliderEg();
JFrame frame = new JFrame("SliderEg");
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();
}
});
}
}