Java JPanels graphics [duplicate] - java

I am trying to create a GUI that will take in the number of circles to draw, and draw them in drawPanel with random locations/sizes. On my actionListener, when I try to draw the circle, it gives me red lines on my drawOval
1st class:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
/**
*
* #author Chris
*
*/
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
/**constructor
* builds the frame
*/
public CirclesPanel(){
//creates buttons and textArea
draw = new JButton("Draw");
clear = new JButton("Clear");
textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
//creats panel
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
//creates subpanel drawPanel
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
//creates subpanel buttonPanel
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
//adds all the content to the frame
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
//reads if the draw button is clicked
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());//takes the count in
repaint();//repaints the picture to add the circles
}
});
//reads if the clear button is clicked
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count=0;//sets the count to 0 so nothing is painted
repaint();//repaints the window
}
});
}
/**Paint component
* draws the random circles
*/
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){ //loop that takes the count and does this "x" times
g.setColor(Color.BLUE);//sets color to blue
x = generator.nextInt(90);//random location for x
y = generator.nextInt(90);//random location for y
diameter = generator.nextInt(30);//random size
g.fillOval(x, y, diameter, diameter);//draws the circle
}
}
}
2nd class
import javax.swing.JFrame;
public class Circles {
public static void main(String[]args){
JFrame frame = new JFrame("Cicles HW9");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CirclesPanel());
frame.pack();
frame.setVisible(true);
}
}

So in your, I did little addition, first of all, I made the whole program in one class(CIRLCES PANEL), IF You want to use the second class, you can use it....
Problem is coming, your program is not the reading the ActionPerformed method for the drawing, means it is not located with the button, now I directly added it with your button(DRAW), now whenever you click on the button, it automatically reads the your textArea value, and draw your circles. I made your text area FINAL, So you can use it anywhere......
Now things that you need to do----
- this program is drawing circle on the whole frame, means not on your drawing Panel, you need to set the values, so it will draw on your draw panel area
- Also you need to add color for your oval, because it will either draw black color circle, which you will not able to see.....
and also one thing I forget to mentioned you, is that your, you also need to add code for your clear method...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
public CirclesPanel(){
JButton draw = new JButton("Draw");
JButton clear = new JButton("Clear");
final JTextArea textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());
repaint();
}
});
}
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){
x = generator.nextInt(90);
y = generator.nextInt(90);
diameter = generator.nextInt(30);
g.drawOval(x, y, diameter, diameter);
}
}
}

What you want to do is drawing some random circles on the drawPanel when button clicked. I write you a simplified version to show how things work.
I only keep the drawButton and paintPanel to keep things simple.
public class PaintFrame extends JFrame {
private JPanel content = new JPanel();
private JButton drawButton = new JButton("Draw");
private PaintPanel paintPanel = new PaintPanel();
public PaintFrame() {
getContentPane().add(content);
content.setLayout(new BorderLayout());
drawButton.setSize(100, 500);
drawButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// drawButton is fired, repaint the paintPanel
paintPanel.repaint();
}
});
content.add(drawButton, BorderLayout.WEST);
content.add(paintPanel, BorderLayout.CENTER);
}
}
You need a new class extending the JPanel and override the paintComponent method to do the paint job for you. This makes sure you are drawing on the panel.
class PaintPanel extends JPanel {
public PaintPanel() {
setSize(500, 500);
setBackground(Color.BLACK);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Random random = new Random();
g.setColor(Color.WHITE);
// draw 5 random circles
int count = 5;
for (int i = 0; i < count; i++) {
g.drawOval(random.nextInt(250), random.nextInt(250),
random.nextInt(250), random.nextInt(250));
}
}
}
Main class
public class DrawMain {
public static void main(String[] args) {
JFrame frame = new PaintFrame();
frame.setDefaultCloseOperation(PaintFrame.EXIT_ON_CLOSE);
frame.setSize(600, 500);
frame.setVisible(true);
}
}

Related

Close Gps on BoxLayout

I have created a setup of buttons using Box.
The problem is there are gaps between all the buttons.
Below is an MCVE version of my code. What I want to achieve is that the buttons "ONE" and "TWO" are touching side by side, with no gap, and buttons "ONE and "ONE" are touching top to bottom with no gap, and for this to continue throughout the setup.
I have read about glue and have tried to use it, but I have not been able to work it out. I am not able to use another layout other than Box as it will not fit in with the rest of my project.
public class Customers {
public static JFrame frame = new JFrame();
public static void frameGui(JPanel panel, String name){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.setSize(1200,500);
frame.setVisible(true);
}
public static void ScrollCustomersGui(){
Box box = Box.createVerticalBox();
box.add(customersTableHeadings(box));
box.add(customersTableHeadings(box));
box.add(customersTableHeadings(box));
box.add(customersTableHeadings(box));
JScrollPane scroll = new JScrollPane(box);
JPanel All = new JPanel(new BorderLayout());
All.add(scroll);
frameGui(All, "Customers");
}
public static JPanel customersTableHeadings(Box panel){
Font font = new Font("Courier", Font.BOLD,12);
JPanel customersTable = new JPanel();
JButton custid = new JButton("ONE");
JButton surname = new JButton("TWO");
customersTable.add(custid);
customersTable.add(surname);
return customersTable;
}
}
BoxLayout is designed to distribute unused space among components; struts, glue and filler won't change this. You can use the approach suggested here and here to alter the preferred size of the enclosing scroll pane. More generally, you can implement the scrollable interface. In addition, Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/** #se https://stackoverflow.com/a/26829171/230513 */
public class Customers {
private static final int N = 16;
private void display() {
Box box = Box.createVerticalBox();
for (int i = 0; i < N; i++) {
box.add(customersTableHeadings());
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(box) {
int w = box.getPreferredSize().width;
int h = box.getPreferredSize().height;
#Override
public Dimension getPreferredSize() {
return new Dimension(9 * w / 8, h / 3);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel customersTableHeadings() {
JPanel customersTable = new JPanel();
JButton custid = new JButton("ONE");
JButton surname = new JButton("TWO");
customersTable.add(custid);
customersTable.add(surname);
return customersTable;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new Customers().display();
});
}
}
I found the answer myself. By adding the horizontal and vertical inside the same loop, and by enclosing this in a JApplet it closes the gap.
Below is a full working version of the code:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Box1 extends JApplet {
public void init() {
Box bv = Box.createVerticalBox();
box(bv);
JScrollPane scroll = new JScrollPane(bv);
JPanel All = new JPanel(new BorderLayout());
All.add(scroll);
Container cp = getContentPane();
cp.add(All);
}
public static void main(String[] args) {
frameGui(new Box1(), "Customers");
}
public static void frameGui (JApplet applet, String name) {
JFrame frame = new JFrame();
frame.getContentPane().removeAll();
frame.setTitle(name);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(applet);
frame.setSize(1200, 500);
applet.init();
applet.start();
frame.setVisible(true);
}
public static Box box(Box boxvert){
for (int i = 0; i < 50; i++){
JTextField one = new JTextField("ONE");
one.setMaximumSize(new Dimension (150,20));
JTextField two = new JTextField("TWO");
two.setMaximumSize(new Dimension (150,20));
Box horizontalBox = Box.createHorizontalBox();
horizontalBox.add(one);
horizontalBox.add(two);
boxvert.add(horizontalBox);
}
return boxvert;
}
}

Trying to paint an Image onto a JPanel

Sorry guys I know there is a lot of info on this topic, but I'm still stuck. I have two panels mainPanel and sidePanel. What I'm trying to do is paint an Image to the sidePanel. My sidePanel will have other components such as buttons and labels. I can add the Image to the sidePanel using a JLabel, however, sizing and positioning the image is a problem. Therefor, I'm experimenting with Graphics g to paint the Image onto the sidePanel instead. If anyone could help much would be appreciated. Thanks all that help.` import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Gui extends JFrame {
private JPanel j;
private ImageIcon i;
public Gui(){
this.setSize(800,600);
this.setUp();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void setUp(){
j = new JPanel();
JPanel contentPanel = new JPanel();
contentPanel.setLayout(new BorderLayout());
contentPanel.setSize(new Dimension(800,600));
JPanel mainPanel = new JPanel();
JPanel sidePanel = new JPanel();
sidePanel.setPreferredSize(new Dimension(200,600));
mainPanel.setPreferredSize(new Dimension(600,600));
ImagePanel v = new ImagePanel();
//v.setBackground(Color.BLUE);
v.setPreferredSize(new Dimension(100,100));
sidePanel.add(v);
mainPanel.setBackground(Color.BLACK);
sidePanel.setBackground(Color.RED);
contentPanel.add(sidePanel, BorderLayout.WEST);
contentPanel.add(mainPanel, BorderLayout.CENTER);
this.add(contentPanel);
}
private class ImagePanel extends JPanel{
public void createImage(Graphics g){
super.paintComponent(g);
ImageIcon i = new ImageIcon("/GUI Practice/src/images.jpeg");
Image ii = i.getImage();
g.drawImage(ii, 10, 10, 90, 90, Color.WHITE, this);
repaint();
validate();
updateUI();
}
}
public static void main(String [] args){
Gui g = new Gui();
}
}
`
Taken from bcash's answer here.
public class ImagePanel extends JPanel {
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters
}
}

How do you limit a component to be in a certain spot

I'm creating a slideshow using swing and trying to place it in the center of my JFrame. The slideshow works fine, but it's taking up the entire center section. How would I limit it to a small place under the banner?
Here's a picture of what it looks like.
Here's a picture of what I want it to look like
This is what I have so far, you run this class.
package com.RBV2.engine;
import javax.swing.*;
import com.RBV2.Settings;
import com.RBV2.panels.News;
import com.RBV2.panels.SlideShow;
import com.RBV2.panels.SlideShow.MovingPanel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
/*
* Author Jon & David
*
*/
#SuppressWarnings("serial")
public class Client extends JFrame implements ActionListener {
private JPanel bottomPanel, news;
private JButton launch;
private JLabel loading, banner;
private MovingPanel slideshow;
protected boolean updated = false;
private void createLayout() {
createPanel();
addPanel();
setVisible(true);
}
private void createPanel() {
bottomPanel = new JPanel(new BorderLayout());
news = new News();
slideshow = new SlideShow.MovingPanel();
launch = new JButton(new URL("http://www.runerebellion.com/clientImages/launch.png"));
loading = new JLabel(new URL("http://www.runerebellion.com/clientImages/loader.gif"));
banner = new JLabel(new URL("http://www.runerebellion.com/clientImages/201457.gif"));
launch.addActionListener(this);
}
private void addPanel() {
setTitle("RuneRebellionV2 Launcher");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
//Bottom Panel
add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.add(new JLabel(" Launcher, release " + Settings.version), BorderLayout.WEST);
bottomPanel.setBackground(Color.BLACK);
bottomPanel.add(launch, BorderLayout.EAST);
launch.setPreferredSize(new Dimension(120, 40));
//News Feed
add(news, BorderLayout.CENTER);
news.add(banner, BorderLayout.CENTER);
banner.setPreferredSize(new Dimension(500, 70));
//slideshow
slideshow.setPreferredSize(new Dimension(610, 331));
add(slideshow, BorderLayout.CENTER);
//Sets size
setSize(Settings.width, Settings.height);
}
public Client() throws IOException {
createLayout();
}
public static void main(String args[]) throws IOException {
final Client l = new Client();
l.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
l.setVisible(true);
}
});
}
These specific lines of code call the slideshow(I commented out exactly where)
private void addPanel() {
setTitle("RuneRebellionV2 Launcher");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
//Bottom Panel
add(bottomPanel, BorderLayout.SOUTH);
bottomPanel.add(new JLabel(" Launcher, release " + Settings.version), BorderLayout.WEST);
bottomPanel.setBackground(Color.BLACK);
bottomPanel.add(launch, BorderLayout.EAST);
launch.setPreferredSize(new Dimension(120, 40));
//News Feed
add(news, BorderLayout.CENTER);
news.add(banner, BorderLayout.CENTER);
banner.setPreferredSize(new Dimension(500, 70));
//slideshow here
slideshow.setPreferredSize(new Dimension(610, 331));
add(slideshow, BorderLayout.CENTER);
//Sets size
setSize(Settings.width, Settings.height);
}
Here is my slideshow class, you may need this also.
package com.RBV2.panels;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class SlideShow extends JFrame {
public static class MovingPanel extends JPanel {
public int i = 0;
public MovingPanel() {
Timer timer = new Timer(3000, new TimerListener());
timer.start();
}
protected void paintComponent(Graphics x) {
super.paintComponent(x);
int y = i % 25;
Image showImg = new ImageIcon("bin/slide/" + y + ".png").getImage();
x.drawImage(showImg, 0, 0, getWidth(), getHeight(), 0, 0, 610, 331, null);
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
i++;
repaint();
if (i >= 5)
i = 1;
}
}
}
}
So my question is how would I limit the slideshow to be in a box in the very center under the banner.
Have a look at this picture (from Border layout Tutorial)
As you are only adding panels to the Center and South(PAGE_END) regions of the layout manager there is no other components to stop the center panel from stretching out as far as it can.
Note this relevant sentence of the tutorial
If the window is enlarged, the center area gets as much of the available space as possible. The other areas expand only as much as necessary to fill all available space. Often a container uses only one or two of the areas of the BorderLayout object — just the center, or the center and the bottom.
You either need to add blank panels on the other sides or make use of an empty border within your Center panel. See here about how to use borders.
I painted the background, then painted the images over the background
protected void paintComponent(Graphics x) {
super.paintComponent(x);
int y = i % 25;
Image showImg = new ImageIcon("bin/slide/" + y + ".png").getImage();
super.paintComponent(x);
x.drawImage((Settings.background).getImage(), 0, 0, getWidth(), getHeight(), this);
x.drawImage(showImg, 360, 260, getWidth(), getHeight(), 0, 0, 110, 31, null);
}

Paint in JPanel is painting in the wrong location and size

I'm working on a Java GUI and I have a JFrame thats 600x800 that I want to split into two portions, the top which has checkboxes for settings and is 600 x 200 and the bottom which is the "canvas" which will be painted on that is 600x600. I have a JFrame that has a JPanel that contains two other JPanels (one for the settings, the other for the canvas). I'm testing the "painting" and for some reason when I try to paint a 600x600 black rectangle, it paints a much smaller rectangle in the area that the settings JPanel occupies. Any ideas what's going on? I'm using the repaint method to call paintComponent and I've tried calling repaint in both the constructor of my JFrame and in the JPanel that is to be painted.
HPAProgram
public class HPAProgram {
public static void main(String[] args) {
MapWindow map = new MapWindow();
}
}
MapWindow
//import java.awt.*;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;
import javax.swing.*; //notice javax
public class MapWindow extends JFrame
{
private static final int WIDTH = 600, HEIGHT = 800;
JPanel panel = new JPanel();
SettingsButtonsPanel button_panel = new SettingsButtonsPanel();
MapImagePanel map_panel = new MapImagePanel();
public MapWindow()
{
setLocationRelativeTo(null);
setTitle("HPA* Test");
setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(panel);
panel.setBounds(0, 0, 600, 800);
//panel.setLayout(new GridBagLayout());
/*GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;*/
panel.add(button_panel);
/*c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;*/
panel.add(map_panel);
button_panel.setLocation(0,0);
/*map_panel.setLocation(0,200);
map_panel.setSize(600,600);*/
map_panel.repaint();
}
}
SettingsButtonsPanel
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class SettingsButtonsPanel extends JPanel implements ItemListener{
private static final int WIDTH = 600, HEIGHT = 200;
private static final int NUM_MAP_TYPE = 2;
private JCheckBox[] map_type;
JPanel panel = new JPanel();
public SettingsButtonsPanel(){
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
this.setBounds(0,0,WIDTH, HEIGHT);
map_type = new JCheckBox[NUM_MAP_TYPE];
map_type[0] = new JCheckBox("Sparse");
map_type[0].setSelected(true);
//map_type[0].setSize(100,100);
map_type[1] = new JCheckBox("Maze");
map_type[1].setSelected(false);
//map_type[1].setSize(100,100);
for(int i = 0; i < NUM_MAP_TYPE; i++)
{
map_type[i].addItemListener(this);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = i;
this.add(map_type[i], c);
}
}
public void itemStateChanged(ItemEvent e)
{
Object source = e.getItemSelectable();
//if(source == )
}
}
MapImagePanel
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class MapImagePanel extends JPanel{
public MapImagePanel()
{
this.setBounds(0,200, 600,600);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0,0,600,600);
}
}
The are a number of misconceptions you seem to have...
JPanel, by default uses a FlowLayout. FlowLayout makes use of each of the components preferred size to determine the size of each component. By default, a component has a preferred size of 0x0.
The layout manager is also responsible for positing the components, so using setBounds and setLocation and setSize is counter productive.
Assuming the size is also not always possible, especially when dealing with text, as this can change size based on differences in the fonts, display drivers, rendering pipelines etc...
This is why Java makes extensive layout managers. Take a look at Laying Out Components Within a Container for more details
Update with simple example
Don't be afaird to mix layouts, using compound components with different layouts, to achieve your desired results, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleLayout100 {
public static void main(String[] args) {
new SimpleLayout100();
}
public SimpleLayout100() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JPanel header = new JPanel();
header.add(new JLabel("Hello, I'm the header"));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(header, BorderLayout.NORTH);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.GREEN);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.setColor(Color.RED);
g2d.fillRect(150, 50, 300, 100);
g2d.dispose();
}
}
}

How to correctly update an Image in a JLabel?

I'm French so my English is quite bad but I have a real problem with java:
I'm trying to show an Image built manually with some fillRect & co.
It works. Next, I want to update this image as a function of the text I enter in the text field. And there is the problem: it doesn't change anything, and if I manually rescale the window of the JFrame, the image shows totally deformed or scaled badly.
I'm a beginner and I have difficulties with GUI, moreso when I want to couple it with Images.
Can you help me? Why doesn't it work as I want? This is my code below, a bit long but actually quite simple ! Thanks :)
I've changed it a bit, this is the 2e VERSION.
Now the problem s that I can't change a condition in order to modify the color of a simple rectangle, try "lol" in the entry field !
CODE VERSION 2
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;
public class Fenetre extends JFrame {
private JFrame frame;
private JPanel container = new JPanel();
private JTextField jtf;
private JLabel label = new JLabel("Commandes ");
private JButton b = new JButton ("OK");
private Graphics graph;
private Image img;
private JLabel screen;
private boolean color;
/**
* Constructeur de l'objet
*/
public Fenetre(){
color = true;
frame = new JFrame();
frame.setTitle("Animation");
frame.setSize(1000, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf = new JTextField();
jtf.setPreferredSize(new Dimension(800, 30));
b.addActionListener(new BoutonListener());
frame.setContentPane(top);
frame.setVisible(true);
paintComponent(graph);
screen = new JLabel( new ImageIcon(img));
top.add(screen);
top.add(label);
top.add(jtf);
top.add(b);
frame.setContentPane(top);
}
class BoutonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(jtf.getText().equals("lol")) lol();
System.out.println("Entry : " + jtf.getText());
}
}
public void paintComponent(Graphics g)
{
if(img == null) {
img = frame.createImage(1000,300);
g = img.getGraphics();
}
g.setColor(Color.white);
g.fillRect(0,0,1000,300);
if(color) g.setColor(Color.orange); else g.setColor(Color.blue);
g.fillRect(8,25,200,100);
g.setColor(Color.green);
g.drawString("Text",10,10);
}
public void lol()
{
if(color) color = false; else color = true;
}
}
PREVIOUS CODE
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ImageIcon;
public class Fenetre extends JFrame {
private JPanel container = new JPanel();
private JTextField jtf;
private JLabel label = new JLabel("Commandes ");
private JButton b = new JButton ("OK");
private Graphics g;
private Image img;
private JLabel screen;
/**
* Constructeur de l'objet
*/
public Fenetre(){
this.setTitle("Animation");
this.setSize(1000, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf = new JTextField();
jtf.setPreferredSize(new Dimension(800, 30));
b.addActionListener(new BoutonListener());
this.setContentPane(top);
this.setVisible(true);
paint(g);
screen = new JLabel( new ImageIcon(img));
top.add(screen);
top.add(label);
top.add(jtf);
top.add(b);
this.setContentPane(top);
}
class BoutonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.out.println("Entry : " + jtf.getText());
if(jtf.getText().equals("lol")) lol();
}
}
#Override
public void paint(Graphics g)
{
if(img == null) {
img = createImage(1000,300);
g = img.getGraphics();
}
g.setColor(Color.white);
g.fillRect(0,0,1000,300);
g.setColor(Color.orange);
g.fillRect(8,25,200,100);
g.setColor(Color.green);
g.drawString("Text",10,10);
}
#Override
public void update(Graphics g)
{
g.setColor(Color.blue);
g.fillRect(8,25,300,100);
}
public void lol()
{
g.setColor(Color.blue);
g.fillRect(8,25,200,100);
}
}
I see several problems in your code:
You are confusing your g member variable with the g parameter of the paint method. When lol is called, g is null and you get a NullPointerException
You should never grab a hold on Graphics (only in really rare cases). Instead you override properly paintComponent() and you use the Graphics parameter to draw what you want. When you want to update the component, you call repaint()
Don't override paint, but override paintComponent()
Don't override paint of JFrame. Use a dedicate component for that. No need to use a JLabel for that, a simple JComponent is enough.
Don't extend JFrame if you are not extending its functionality.
After adding components to the component hierarchy, call revalidate()
Fix those issues and come back with another question if you still have problems.
You should probably consider reading this tutorial and the few next steps. It will show you basic examples of things similar to what you are trying to do.
EDIT:
I took your V2 code and patched it as I could. This is very far from perfect but you should get the gist of how you can do this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Fenetre extends JComponent {
private boolean color;
/**
* Constructeur de l'objet
*/
public Fenetre() {
color = true;
setPreferredSize(new Dimension(1000, 300));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, 1000, 300);
if (color) {
g.setColor(Color.orange);
} else {
g.setColor(Color.blue);
}
g.fillRect(8, 25, 200, 100);
g.setColor(Color.green);
g.drawString("Text", 10, 10);
}
public void lol() {
if (color) {
color = false;
} else {
color = true;
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
protected static void initUI() {
JFrame frame = new JFrame();
frame.setTitle("Animation");
frame.setSize(1000, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JPanel container = new JPanel();
final JTextField jtf = new JTextField();
final Fenetre fenetre = new Fenetre();
JLabel label = new JLabel("Commandes ");
JButton b = new JButton("OK");
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
jtf.setPreferredSize(new Dimension(800, 30));
class BoutonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (jtf.getText().equals("lol")) {
fenetre.lol();
}
System.out.println("Entry : " + jtf.getText());
}
}
b.addActionListener(new BoutonListener());
top.add(fenetre);
top.add(label);
top.add(jtf);
top.add(b);
top.revalidate();
frame.setContentPane(top);
frame.setVisible(true);
}
}
Your Swing graphics programming has several significant problems, and I urge you to go through the tutorials to learn how to do this better. For example, you are
calling the paint method directly -- something you should almost never do except in very special situations (this is not one of them)
Drawing directly in the JFrame's paint(...) method. Instead you will want to draw in the paintComponent(...) method override of a class derived from JComponent such as JPanel.
Calling update unnecessarily as if this were an AWT program. You don't do this in Swing unless you're changing the Look & Feel.
Again, take a look at the tutorials on this -- you will not regret doing this, trust me.
edit -- too slow! 1+ to Guillaume

Categories

Resources