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);
}
}
Related
I have a JTextField inside a JPanel . The user can type text as big as she wants in the textfield , however horizontal scrolling should appear when the text goes beyond the screen of the textfield. At this point if the user backspace the text and shrink the text within the screen of the textfield , the scrolling should disappear. So basically scrolling should appear only when its needed. How to do it ? Help please.
If you don't like the behavior of the JScrollPane + JTextField, you need to use JScrollBar#setModel(BoundedRangeModel) + JTextField#getHorizontalVisibility():
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicScrollBarUI;
public class TextFieldScrollBarTest {
private static final String TEXT = "javascript:(function(){var l=location,m=l.href.match('^(https?://)(.+)(api[^+]+|technotes[^+]+)');if(m)l.href=m[1]+'docs.oracle.com/javase/8/docs/'+decodeURIComponent(m[3]).replace(/\\+.*$/,'').replace(/\\[\\]/g,':A').replace(/, |\\(|\\)/g,'-');}());";
public JComponent makeUI() {
JScrollPane scroll = new JScrollPane(new JTextField(TEXT));
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
JTextField textField = new JTextField(TEXT);
JScrollBar scroller = new JScrollBar(Adjustable.HORIZONTAL) {
#Override public void updateUI() {
//super.updateUI();
setUI(new ArrowButtonlessScrollBarUI());
}
#Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = 5;
return d;
}
};
scroller.setModel(textField.getHorizontalVisibility());
Box box = Box.createVerticalBox();
box.add(scroll);
box.add(Box.createVerticalStrut(50));
box.add(textField);
box.add(Box.createVerticalStrut(2));
box.add(scroller);
box.add(Box.createVerticalGlue());
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
p.add(box, BorderLayout.NORTH);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TextFieldScrollBarTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class ZeroSizeButton extends JButton {
private static final Dimension ZERO_SIZE = new Dimension();
#Override public Dimension getPreferredSize() {
return ZERO_SIZE;
}
}
class ArrowButtonlessScrollBarUI extends BasicScrollBarUI {
private static final Color DEFAULT_COLOR = new Color(220, 100, 100);
private static final Color DRAGGING_COLOR = new Color(200, 100, 100);
private static final Color ROLLOVER_COLOR = new Color(255, 120, 100);
#Override protected JButton createDecreaseButton(int orientation) {
return new ZeroSizeButton();
}
#Override protected JButton createIncreaseButton(int orientation) {
return new ZeroSizeButton();
}
#Override protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
//Graphics2D g2 = (Graphics2D) g.create();
//g2.setPaint(new Color(100, 100, 100));
//g2.fillRect(r.x, r.y, r.width - 1, r.height - 1);
//g2.dispose();
}
#Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
JScrollBar sb = (JScrollBar) c;
if (!sb.isEnabled()) {
return;
}
BoundedRangeModel m = sb.getModel();
int iv = m.getMaximum() - m.getMinimum() - m.getExtent() - 1; // -1: bug?
if (iv > 0) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color;
if (isDragging) {
color = DRAGGING_COLOR;
} else if (isThumbRollover()) {
color = ROLLOVER_COLOR;
} else {
color = DEFAULT_COLOR;
}
g2.setPaint(color);
g2.fillRect(r.x, r.y, r.width - 1, r.height - 1);
g2.dispose();
}
}
}
I'm making a score-keeping program, but I'm running into a problem. What I've tried to do is have a JPanel at the top that contains two JPanels, which, in turn, contains two team names. I'm confused as to why the two JLabels at the top of the program aren't centered inside of the JPanels they're contained in.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ScoreFrame extends JFrame {
private static final Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
private static final int WIDTH = SCREEN_SIZE.width;
private static final int HEIGHT = SCREEN_SIZE.height;
private final JTextField[] nameField = new JTextField[] { new JTextField(), new JTextField() };
private final JLabel[] nameLabel = new JLabel[] { new JLabel("Team 1"), new JLabel("Team 2") };
private final GridBagLayout gridBag = new GridBagLayout();
private final GridBagConstraints constraints = new GridBagConstraints();
private final JPanel topPanel = new JPanel();
public ScoreFrame() {
super();
setResizable(false);
setSize(SCREEN_SIZE);
setLayout(gridBag);
setUndecorated(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(new EscapeListener());
addComponents();
}
private void addComponents() {
addToTopPanel();
constraints.insets = new Insets(0, 0, (int) (HEIGHT * (double) 4 / 5), 0);
gridBag.setConstraints(topPanel, constraints);
add(topPanel);
}
private void addToTopPanel() {
final JPanel[] teamPanel = new JPanel[] { new JPanel(), new JPanel() };
topPanel.setLayout(gridBag);
topPanel.setSize(new Dimension(WIDTH, HEIGHT / 5));
Dimension teamPanelSize = new Dimension(WIDTH / 2, HEIGHT / 5);
teamPanel[0].setSize(teamPanelSize);
teamPanel[1].setSize(teamPanelSize);
Font nameFont = new Font("Times New Roman", Font.PLAIN, 50);
nameLabel[0].setFont(nameFont);
nameLabel[1].setFont(nameFont);
teamPanel[0].add(nameLabel[0]);
teamPanel[1].add(nameLabel[1]);
gridBag.setConstraints(teamPanel[0], constraints);
constraints.gridx = 1;
gridBag.setConstraints(teamPanel[1], constraints);
topPanel.add(teamPanel[0]);
topPanel.add(teamPanel[1]);
}
public void paint(Graphics g) {
super.paint(g);
int strokeSize = ((WIDTH + HEIGHT) / 2) / 300;
if (strokeSize < 1) {
strokeSize = 1;
}
final int fontSize = (int) (strokeSize * 12.5);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(strokeSize));
g.drawLine(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 5);
g.drawLine(WIDTH / 2, (int) (HEIGHT * (double) 105 / 400), WIDTH / 2, HEIGHT);
g.drawLine(0, HEIGHT / 5, WIDTH, HEIGHT / 5);
g.drawRect((int) (WIDTH * (double) 45 / 100), HEIGHT / 5, WIDTH / 10, (int) (HEIGHT * (double) 3 / 20));
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setFont(new Font("Times New Roman", Font.PLAIN, fontSize));
g.drawString("Errors", (int) (WIDTH * (double) 101 / 220), HEIGHT / 4);
}
private JFrame getFrame() {
return this;
}
public static void main(final String args[]) {
new ScoreFrame().setVisible(true);
}
public class EscapeListener implements KeyListener {
public void keyPressed(final KeyEvent event) {
if (event.getKeyCode() == 27) {
final int choice = JOptionPane.showConfirmDialog(getFrame(), "Do you want to exit the program?");
if (choice == 0) {
System.exit(0);
}
}
}
public void keyReleased(final KeyEvent event) {
}
public void keyTyped(final KeyEvent event) {
}
}
}
Invoking pack() is a critical step in using layouts. This example uses JLabel.CENTER and GridLayout to center the labels equally as the frame is resized. For simplicity, the center panel is simply a placeholder. This somewhat more complex example uses a similar approach along with java.text.MessageFormat.
Addendum: But how would I apply pack() to my code?
Simply invoke pack() as shown in the examples cited. I don't see an easy way to salvage your current approach of setting sizes extrinsically. Instead, override getPreferredSize() in a JPanel for your main content. No matter the screen size, your implementation of paintComponent() should adapt to the current size, for example.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/14422016/230513 */
public class Scores {
private final JLabel[] nameLabel = new JLabel[]{
new JLabel("Team 1", JLabel.CENTER),
new JLabel("Team 2", JLabel.CENTER)};
private void display() {
JFrame f = new JFrame("Scores");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel teamPanel = new JPanel(new GridLayout(1, 0));
teamPanel.add(nameLabel[0]);
teamPanel.add(nameLabel[1]);
f.add(teamPanel, BorderLayout.NORTH);
f.add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
}, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Scores().display();
}
});
}
}
Currently, I have to JComponents contained in a JPanel with a vertical box layout.
This way, I can have the first component centered, as shown below, and have the bottom component (which is quite long) below. However, since the bottom component is very long I wanted to add a slider just for that specific component. This way, the user can see all of the bottom component with the upper component remaining centered. However, my code below doesn't fix anything and the scrollbar never even works. The only information about GPComponent and GPinfinity you need to know is they override the preferredSize, minimumSize, maximumSize, and paintComponent methods (they extend JComponent).
JFrame frame = new JFrame();
JPanel panel = new JPanel();
GPComponent gp = new GPComponent(n, k);
GPinfinityComponent gpi = new GPinfinityComponent(n, k);
Box box = new Box(BoxLayout.Y_AXIS);
panel.add(Box.createVerticalGlue());
panel.add(gp);
panel.add(Box.createVerticalGlue());
JScrollPane thePane = new JScrollPane(gpi, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
panel.add(thePane);
frame.pack();6
frame.add(panel, BorderLayout.CENTER); // just to be clear
frame.setVisible(true);
final int FRAME_WIDTH = 600;
final int FRAME_HEIGHT = 600;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("GP("+n+", "+k+")");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Also: the maximumSize=minimumSize=preferredSize for both components
For the circular one the dimensions are (350, 350) and for the other the dimensions are (5000, 150).
You state:
...and for the other the dimensions are (5000, 150).
If this is the component that is supposed to show the scrollbars, the Java is telling you otherwise, that it is in fact much shorter than you suppose it to be. I wonder if you're setting size instead of preferredSize. You actually should not be setting either but rather should override getPreferredSize() and have it return a dimension appropriate for the component.
For more detailed help, consider creating and posting a minimal example program.
Edit
For example, my MCVE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.*;
#SuppressWarnings("serial")
public class PreferredSizeEg extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
public PreferredSizeEg() {
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(new CenterImagePanel());
JScrollPane scrollpane = new JScrollPane(new LongImagePanel(),
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
setLayout(new BorderLayout());
add(centerPanel, BorderLayout.CENTER);
add(scrollpane, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class LongImagePanel extends JPanel {
private static final int LI_PREF_W = 5000;
private static final int LI_PREF_H = 150;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int index = 0;
int spriteWidth = 50;
while ((index) * spriteWidth < getWidth()) {
Color c = index % 2 == 0 ? Color.green : Color.red;
g.setColor(c);
int x = 2 + index * spriteWidth;
int y = 2;
int width = getHeight() - 4;
int height = width;
g.fillOval(x, y, width, height);
index++;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(LI_PREF_W, LI_PREF_H);
}
}
private class CenterImagePanel extends JPanel {
private static final int CIP_PREF_W = 200;
private static final int CIP_PREF_H = CIP_PREF_W;
public CenterImagePanel() {
setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.green);
int x = 5;
int y = x;
int width = getWidth() - 2 * x;
int height = getHeight() - 2 * y;
g.fillOval(x, y, width, height);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(CIP_PREF_W, CIP_PREF_H);
}
}
private static void createAndShowGui() {
PreferredSizeEg mainPanel = new PreferredSizeEg();
JFrame frame = new JFrame("PreferredSizeEg");
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();
}
});
}
}
Which displays as:
I'm trying to create a GUI where I can create custom colors. I have a feature that lets the user preview the color before submitting the color. I can't get the Icon to display at all. The actual problem is in my ColorFrame class. The color Icon(a JLabel, color) is created in the actionperformed() method.
The code that creates the Icon(The ButtonListener class):
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ColorFrame extends JFrame implements ActionListener {
private JPanel colorPanel;
private JPanel labelPanel;
private JPanel buttonPanel;
private JLabel labelRed;
private JLabel labelGreen;
private JLabel labelBlue;
private JLabel color;
private JTextField redField;
private JTextField greenField;
private JTextField blueField;
private JButton preview;
private JButton submit;
private int redInt;
private int blueInt;
private int greenInt;
private int width = 30;
private int height = 30;
public ColorFrame(int x, int y)
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //closes all frames for some reason
this.pack();
this.setLocation(x, y);
buttonPanel = new JPanel();
this.getContentPane().add(buttonPanel,BorderLayout.SOUTH);
preview = new JButton("Preview Color");
preview.addActionListener(new ButtonListener());
buttonPanel.add(preview);
createColorPanel();
createLabelPanel();
this.setVisible(true);
}
class ButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
//in the gui, there are three jtextfieilds that represent color values. the first is red, the second is green, and the last is blue.
redInt = Integer.parseInt(redField.getText());
greenInt = Integer.parseInt(greenField.getText());
blueInt = Integer.parseInt(blueField.getText());
color = new JLabel(new ColorIcon(redInt,greenInt,blueInt));
buttonPanel.add(color,BorderLayout.SOUTH);
print(redInt,greenInt, blueInt);
}
}
private void createColorPanel()
{
colorPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//creates the three textfields to input rgb values.
//the first is r, second, b third g
redField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 0;
c.insets = new Insets(10,0,0,10);
colorPanel.add(redField,c);
greenField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.0;
c.gridx = 1;
c.gridy = 1;
colorPanel.add(greenField,c);
blueField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 2;
colorPanel.add(blueField,c);
redField.addActionListener(this);
greenField.addActionListener(this);
blueField.addActionListener(this);
this.add(colorPanel, BorderLayout.EAST);
}
public void actionPerformed(ActionEvent arg0) {
redInt = Integer.parseInt(redField.getText());
greenInt = Integer.parseInt(greenField.getText());
blueInt = Integer.parseInt(blueField.getText());
// creates the color icon. It works sometimes, but not every time.
color = new JLabel(new ColorIcon(redInt,greenInt,blueInt));
buttonPanel.add(color);
print(redInt,greenInt, blueInt);
}
private void print(int a, int b, int c)
{
// just to see if the actionperformed() method works.
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
public Dimension getPreferredSize() {
return new Dimension(300,300);
}
public static void main(String[] args)
{
ColorFrame frame = new ColorFrame(200,200);
}
}
Color Icon class:
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.Icon;
public class ColorIcon implements Icon{
private final int size = 30;
private int red;
private int green;
private int blue;
public ColorIcon(int r, int g, int b)
{
this.red = r;
this.green = g;
this.blue = b;
}
#Override
public int getIconHeight() {
// TODO Auto-generated method stub
return size;
}
#Override
public int getIconWidth() {
// TODO Auto-generated method stub
return size;
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
// TODO Auto-generated method stub
Graphics2D g2 = (Graphics2D) g;
Rectangle2D.Double square = new Rectangle2D.Double(50, 50, size, size);
g2.setColor(new Color(red,green,blue));
g2.fill(square);
}
}
There are a number of possible ways you can handle this. One is to create a panel where you can set the color and paint the entire panel. Something like
private class ColorPanel extends JPanel {
private Color color = Color.BLUE;
public void setColor(Color color) {
this.color = color;
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
}
You can just set the color. Another thing I noticed is that you are trying to add the new label to the button panel, but the button panel is in the south of the frame. I think you want the label in the center of the frame. So you would add the new label to the CENTER by itself, and not to the button panel.
Here's a refactor of your code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class ColorFrame extends JFrame implements ActionListener {
private JPanel colorPanel;
private JPanel buttonPanel;
private JLabel color;
private JTextField redField;
private JTextField greenField;
private JTextField blueField;
private JButton preview;
private int redInt;
private int blueInt;
private int greenInt;
private ColorPanel cPanel = new ColorPanel();
public ColorFrame(int x, int y) {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
JPanel preferredSizeWrapper = new JPanel(new GridBagLayout());
preferredSizeWrapper.add(cPanel);
this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
preview = new JButton("Preview Color");
preview.addActionListener(new ButtonListener());
buttonPanel.add(preview);
createColorPanel();
this.add(preferredSizeWrapper);
this.pack();
this.setLocation(x, y);
this.setVisible(true);
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
// in the gui, there are three jtextfieilds that represent color
// values. the first is red, the second is green, and the last is
// blue.
redInt = Integer.parseInt(redField.getText());
greenInt = Integer.parseInt(greenField.getText());
blueInt = Integer.parseInt(blueField.getText());
// new ColorIcon(redInt, greenInt, blueInt)
cPanel.setColor(new Color(redInt, greenInt, blueInt));
}
}
private class ColorPanel extends JPanel {
private Color color = Color.BLUE;
public void setColor(Color color) {
this.color = color;
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
}
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
}
private void createColorPanel() {
colorPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// creates the three textfields to input rgb values.
// the first is r, second, b third g
redField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 0;
c.insets = new Insets(10, 0, 0, 10);
colorPanel.add(redField, c);
greenField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.0;
c.gridx = 1;
c.gridy = 1;
colorPanel.add(greenField, c);
blueField = new JTextField(2);
c.fill = GridBagConstraints.VERTICAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 2;
colorPanel.add(blueField, c);
redField.addActionListener(this);
greenField.addActionListener(this);
blueField.addActionListener(this);
this.add(colorPanel, BorderLayout.EAST);
}
public void actionPerformed(ActionEvent arg0) {
redInt = Integer.parseInt(redField.getText());
greenInt = Integer.parseInt(greenField.getText());
blueInt = Integer.parseInt(blueField.getText());
colorPanel.add(color);
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ColorFrame frame = new ColorFrame(200, 200);
}
});
}
}
Another Option is just use a regular JPanel
private JPanel createCPanel() {
return new JPanel() {
{
setBackground(Color.BLUE);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
};
}
and just call setBackground(Color) on the panel. You need to keep in mind the above changes also though.
Instead of creating the color icon try using setting the background color to what you want and then set the size of the label.
I create two rectangleComponents in my GameFrame but they are never at the same location, despite the components being constructed with the same X,Y Coords. Anyone know how to fix this? I also make a JLabel on the top green rectangle, but it never shows up.
Thank you for your time.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameFrame extends JFrame
{
private SpellBarComponent bar;
private JPanel mainPanel = new JPanel();
private JPanel buttonPanel = new JPanel();
Color green = new Color(29, 180, 29);
Color red = new Color(255, 0, 0);
private RectangleComponent life;
private RectangleComponent death;
public GameFrame(char x)
{
setSize(1024, 768);
setTitle("Game");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
createPanels(x);
buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
mainPanel.setLayout(new GridLayout(0, 2, 5, 5));
repaint();
getContentPane().add(mainPanel, BorderLayout.CENTER);
getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
setLocationByPlatform(true);
setVisible(true);
}
public RectangleComponent getLife()
{
return life;
}
private void createHealth()
{
life = new RectangleComponent(green, true);
death = new RectangleComponent(red, false);
}
private void createPanels(char x)
{
createBar(x);
createHealth();
mainPanel.add(buttonPanel);
mainPanel.add(life);
mainPanel.add(death);
buttonPanel.add(bar.getSpell1());
buttonPanel.add(bar.getSpell2());
buttonPanel.add(bar.getSpell3());
}
private void createBar(char x)
{
bar = new SpellBarComponent(x);
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.JLabel;
public class RectangleComponent extends JComponent
{
private Color color;
private int width;
private int height;
private RoundRectangle2D roundedRectangle;
private int origWidth;
private JLabel label;
private boolean wantLabel;
public RectangleComponent(Color color, int width, int height, boolean wantLabel)
{
this.width = width;
this.height = height;
this.color = color;
origWidth = width;
this.wantLabel = wantLabel;
if(wantLabel)
{
label = new JLabel(this.width + "/" + origWidth);
label.setLabelFor(this);
}
}
public RectangleComponent(Color color, boolean wantLabel)
{
width = 125;
height = 18;
this.color = color;
origWidth = width;
this.wantLabel = wantLabel;
if(wantLabel)
{
label = new JLabel(this.width + "/" + origWidth);
label.setLabelFor(this);
}
}
public void paintComponent(Graphics g)
{
Graphics2D graphics2 = (Graphics2D) g;
roundedRectangle = new RoundRectangle2D.Float(10, 10, width, height, 10, 10);
graphics2.setPaint(color);
graphics2.fill(roundedRectangle);
graphics2.draw(roundedRectangle);
if(wantLabel)
label.setText(this.width + "/" + origWidth);
}
public Dimension getPreferredSize()
{
return (new Dimension(width, height));
}
public void subtractLife(int amount)
{
width -= amount;
if(width > 0)
{
roundedRectangle.setRoundRect(10, 10, width, height, 10, 10);
repaint();
}
else
width = 0;
}
public void addLife(int amount)
{
width += amount;
if(width < origWidth)
{
roundedRectangle.setRoundRect(10, 10, width, height, 10, 10);
repaint();
}
else width = origWidth;
}
}
The bounds of a component are overridden by the layout manager of the parent component. Since mainPanel is using a GridLayout, all components in it will be in different grid cells. If you want to manually position these components, set the layout manager of mainPanel to null.