I am a total Beginner and while I had most of the Application right away. I can t make a background picture for my swing gui.
I ve read that you should do it with the overriding the paint methode, which I did. But somewhere I am making a mistake. Since nothing chances, except that the Button is invisible until I go over it with the Mouse. I tried several things, maybe one of you can see the Problem and help me out? Thanks a lot :)
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
/**
*
* #author Shore
*/
public class GUI extends JFrame implements ActionListener {
Container c;
JButton überprüfungsButton = new JButton();
JTextField eingabeTextField = new JTextField();
JTextArea ausgabeTextFeld = new JTextArea();
Image hintergrundBild;
public GUI(){
this.hintergrundBild = Toolkit.getDefaultToolkit().getImage( "Bild2.jpg" );
c = getContentPane();
c.setLayout(new BorderLayout());
c.setBackground(Color.LIGHT_GRAY);
überprüfungsButton = new JButton("Test");
überprüfungsButton.addActionListener(this);
c.add(überprüfungsButton, BorderLayout.CENTER);
eingabeTextField = new JTextField(40);
c.add(eingabeTextField, BorderLayout.PAGE_START);
eingabeTextField.setOpaque(false);
ausgabeTextFeld = new JTextArea(30,30);
c.add(ausgabeTextFeld, BorderLayout.PAGE_END);
ausgabeTextFeld.setOpaque(false);
}
public static void main(String[] args) {
GUI fenster = new GUI();
fenster.setTitle("Für");
fenster.setSize(800, 800);
fenster.setVisible(true);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
protected void paintComponent(Graphics g) {
if (hintergrundBild != null) {
g.drawImage(hintergrundBild, 0, 0, getWidth(), getHeight(), null);
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == überprüfungsButton){
Thanks whoever took the Time to take a look at it.
Update: I actually can resolve the Problem with Netbeans and the swing-GUI Creator.
However, I am still very curious!
If you could still help me, I would appreciate it.
JFrame does not override paintComponent so Swing will not invoke it.
Adding the #Override annotation above the method will show that the method is not contained in the super class.
The simplest way to implement a background image is to create a subclass of JPanel and override paintComponent there.
Update:
There are many examples on the web where the class JFrame is extended. From a design point is view this is not necessary as you typically do not any new functionality to the frame. For this reason just creating a direct instance & using is better (shown):
public class BackGroundProblem {
public static void main(String[] args) throws IOException {
final Image image = ImageIO.read(new URL("http://news.beloblog.com/ProJo_Blogs/architecturehereandthere/hallstattsumm.jpg"));
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JPanel backgroundPanel = new ImagePanel(image);
backgroundPanel.add(new JButton("Sample Button 1"));
backgroundPanel.add(new JButton("Sample Button 2"));
frame.add(backgroundPanel);
frame.setLocationByPlatform(true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class ImagePanel extends JPanel {
private static final long serialVersionUID = 1L;
private Image image;
ImagePanel(Image image) {
this.image = image;
};
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
}
Related
I am currently working on a little game but I just encountered a problem:
I have three classes, the first one is the JFrame:
public class Game
{
public static void main(String[] args)
{
new Game().gui();
}
public void gui()
{
DrawPanel panel = new DrawPanel();
JFrame frame = new JFrame("Test");
//frame.add(panel);
frame.add(new MainMenu());
frame.setSize(800, 700);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
}
}
Now I have two other classes, one is the mainMenu, currently consisting of just one JButton.
I decided to make the menu its own class because later, I want to call the menu by pressing escape, but the problem is that (for testing reasons) I want to draw an rectangle when "start" is pressed. I tried different approaches but nothing happens.
public class MainMenu extends JPanel implements ActionListener
{
GamePanel panel = new GamePanel();
public MainMenu()
{
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JButton b1 = new JButton("Start");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipadx = 200;
b1.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
add(b1, c);
}
}
public class DrawPanel extends JPanel
{
public void paint(Graphics g)
{
g.drawRect (10, 10, 200, 200);
}
}
There are several errors I found in your code:
You're not adding your DrawPanel to anything because this line
frame.add(panel);
is commented, so, that leads us to the next problem:
You're overriding paint() method instead of paintComponent() and also don't forget to call
super.paintComponent();
at the very beginning of the method. Without it, you're preventing your code to keep painting the rest of the components. See Custom painting in Swing
That still doesn't makes anything appear because you haven't declared a location for your DrawPanel and thus it's taking JFrame's default Layout Manager which is BorderLayout and it's default location when not specified is CENTER, and as you're adding new MainMenu() to it on the same position it replaces the DrawPanel panel, since only one component can exist on the same position.
Instead try and place the DrawPanel to the CENTER and the MainMenu to the SOUTH. It now should look like this:
Don't forget to place your program on the Event Dispatch Thread (EDT) by writing your main method as follows:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
You're implementing ActionListener on MainMenu but not implementing it's methods, remove it or implement the actionPerformed method and move the code inside the b1 action listener to it. However I highly recommend you to take at Should your class implement ActionListener or use an object of an anonymous ActionListener class too
You're playing with MainMenu's JPanel visibility, instead you should try using a CardLayout or consider using JDialogs.
For example I would make a JDialog and place the JButton there, so it will open the JFrame with the Rectangle drawn in it.
Now, the code that made the above output and follows all recommendations (but #6) is:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Game().gui();
}
});
}
public void gui() {
DrawPanel panel = new DrawPanel();
JFrame frame = new JFrame("Test");
frame.add(panel, BorderLayout.CENTER);
frame.add(new MainMenu(), BorderLayout.SOUTH);
frame.setSize(400, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
}
}
class MainMenu extends JPanel {
// GamePanel panel = new GamePanel();
public MainMenu() {
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
JButton b1 = new JButton("Start");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipadx = 200;
b1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
add(b1, c);
}
}
class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(10, 10, 200, 200);
}
}
As suggested in the comments by #MadProgrammer, you can also override the getPreferredSize() method of your DrawPanel and then call frame.pack():
Your DrawPanel class should now look like this:
class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(10, 10, 200, 200);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
}
I'm trying to draw a basic object to a JPanel
although it doesn't seem to be working.
I'm certain I am doing something wrong with where the paint method
is being called
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class testGui {
static colors gc_colors;
static gui gc_gui;
public static void main(String[] args) {
gc_colors = new colors();
gc_gui = new gui();
gc_gui.cv_frame.setVisible(true);
}
public static class colors {
Color cv_ltGrey;
Color cv_mdGrey;
Color cv_dkGrey;
public colors() {
cv_ltGrey = Color.decode("#DDDDDD");
cv_mdGrey = Color.decode("#CCCCCC");
cv_dkGrey = Color.decode("#111111");
}
}
public static class gui {
JFrame cv_frame;
JPanel cv_panel;
JPanel cv_content;
public gui() {
cv_frame = new JFrame();
cv_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cv_frame.setTitle("Test GUI");
cv_frame.setSize(600, 400);
cv_frame.setLayout(new FlowLayout());
cv_panel = new JPanel();
cv_panel.setBackground(gc_colors.cv_ltGrey);
cv_panel.setPreferredSize(new Dimension(500, 300));
cv_frame.add(cv_panel);
cv_content = new content();
cv_panel.add(cv_content);
}
}
public static class content extends JPanel {
public void paint(Graphics graphic) {
super.paint(graphic);
draw(graphic);
}
public void update() {
repaint();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.setPaint(gc_colors.cv_ltGrey);
graphic2D.fillRect(10, 10, 100, 100);
}
}
}
I have a class for my gui which I am adding a JPanel to (a light grey one).
Which I am then trying to add my drawing to using a JPanel extended class
called content.
When I run it though it seems to create the grey JPanel which I want but
the drawing is just a tiny white square and I'm not sure why.
So, you content panel has a default preferred size of 0x0, FlowLayout honours the preferredSize of its components (with a little margin), hence the reason why you have a nice little small white rectangle.
What you need to do is override the getPreferredSize method of the content panel and return a suitable size, for example
public static class content extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(120, 120);
}
public void paint(Graphics graphic) {
super.paint(graphic);
draw(graphic);
}
public void update() {
repaint();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.setPaint(gc_colors.cv_ltGrey);
graphic2D.fillRect(10, 10, 100, 100);
}
}
I've decided to just leave out the second JPanel altogether.
It was too much of a hassle to put the JPanel inside of another JPanel
so instead I am only going to use a single JPanel
public static class gui {
JFrame cv_frame;
JPanel cv_panel;
JPanel cv_content;
public gui() {
cv_frame = new JFrame();
cv_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cv_frame.setTitle("Test GUI");
cv_frame.setSize(600, 400);
cv_frame.setLayout(new FlowLayout());
cv_content = new content();
cv_content.setBackground(gc_colors.cv_ltGrey);
cv_content.setPreferredSize(new Dimension(500, 300));
cv_frame.add(cv_content);
}
}
I want to create a java Application like a widget. Here is my code below
package newpackage;
public class MainFrame extends JFrame {
JLabel imageLabel = new JLabel();
public MainFrame() {
try {
this.setUndecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(360, 360));
ImageIcon ii = new ImageIcon(this.getClass().getResource("imageexcel.gif"));
imageLabel.setIcon(ii);
add(imageLabel, java.awt.BorderLayout.CENTER);
this.setVisible(true);
Shape shape=new Ellipse2D.Float(0,0,360,360);
AWTUtilities.setWindowShape(this, shape);
AWTUtilities.setWindowOpaque(this, false);
imageLabel.add(new JButton("START"));
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
new MainFrame();
}
}
In the above code, I have done the following:
Created a Frame
Removed the Title Bar
Added the Background using JLabel
Changed the shape of window as circle according to the shape of image
Now I would like to add some components in to it and perform some action with them but no component is visible after adding.
I have tried adding to Frame as well as JLabel and no use from either.
This is the image i used for background
Please help me to proceed further....
Thanking you
JLabels use null layouts by default, and so your button will default to size 0,0. Try giving it a decent layout manager, even FlowLayout would likely work. Another solution is to keep the null layout and set the sizes and positions of added components, but this route is a dangerous route and one I don't recommend.
Actually a GridBagLayout works nice to center the components. Also add all components before calling setVisible(true):
imageLabel.setLayout(new GridBagLayout());
this.setUndecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(360, 360));
ImageIcon ii = new ImageIcon(this.getClass().getResource("imageexcel.gif"));
imageLabel.setIcon(ii);
add(imageLabel, java.awt.BorderLayout.CENTER);
imageLabel.add(new JButton("START"));
this.setVisible(true);
or better?
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.net.URL;
import javax.swing.*;
import com.sun.awt.AWTUtilities;
#SuppressWarnings("serial")
public class MainPanelOvalFrame extends JPanel {
private static final String RESOURCE_PATH = "imageexcel.gif";
private Window window;
private Image img;
public MainPanelOvalFrame(Window window, Image image) {
this.window = window;
this.img = image;
setLayout(new GridBagLayout());
add(new JButton(new StartAction("Start", KeyEvent.VK_S)));
int w = image.getWidth(this);
int h = image.getHeight(this);
Shape shape = new Ellipse2D.Float(0, 0, w, h);
AWTUtilities.setWindowShape(window, shape);
AWTUtilities.setWindowOpaque(window, false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int w = img.getWidth(this);
int h = img.getHeight(this);
return new Dimension(w, h);
}
private class StartAction extends AbstractAction {
public StartAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
window.dispose();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame();
frame.setUndecorated(true);
URL imgUrl = MainPanelOvalFrame.class.getResource(RESOURCE_PATH);
Image image = new ImageIcon(imgUrl).getImage();
MainPanelOvalFrame mainPanel = new MainPanelOvalFrame(frame, image);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You just need to set a Layout manager for imageLabel ,or use null as the Layout manager, then set the size and location of the JButton manually.
to use Layout Manager
imageLabel.setIcon(ii);
imageLabel.setLayout(new FlowLayout());
imageLabel.add(new JButton("START"));
//need to setLayout and add JButton before setVisible(true)
add(imageLabel, java.awt.BorderLayout.CENTER);
this.setVisible(true);
to use null layout
JButton j=new JButton("START");
j.setSize(100,50);
j.setLocation(imageLabel.getWidth()/2-j.getWidth()/2, imageLabel.getHeight()/2-j.getHeight()/2);
//then add Button into imageLabel
imageLabel.add(j);
Layout manager is usually recommended because it can fit different environment.
For a programming class, I was asked to create a replica of an iCalendar app. I'm using JAVA to code it, and JFrame and JPanel to draw it. Here is a SSCCEE of my problem:
import java.awt.*;
import javax.swing.*;
public class Mainie extends JFrame {
private JButton back = new TriangleButton(true),
front = new TriangleButton(false);
public Mainie(){
super();
setSize(800, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel months = new JPanel();
final JPanel days = new JPanel();
JLabel one = new JLabel("Hallo");
one.setHorizontalAlignment(JLabel.CENTER);
back.setHorizontalAlignment(SwingConstants.LEFT);
front.setHorizontalAlignment(SwingConstants.RIGHT);
months.setLayout(new BorderLayout());
months.add(back, BorderLayout.WEST);
months.add(one, BorderLayout.CENTER);
months.add(front, BorderLayout.EAST);
days.setLayout(new GridLayout(1,1));
days.add(new JButton("Meister Camickr"));
months.setAlignmentX(CENTER_ALIGNMENT);
add(months, BorderLayout.NORTH);
add(days, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args){
new Mainie();
}
}
class TriangleButton extends JButton {
private Shape triangle = createTriangle();
public void paintBorder(Graphics g) {
((Graphics2D) g).draw(triangle);
}
public void paintComponent(Graphics g) {
((Graphics2D) g).fill(triangle);
}
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
public boolean contains(int x, int y) {
return triangle.contains(x, y);
}
public TriangleButton(boolean pointLeft) {
super();
if (!pointLeft)
this.triangle = createRTriangle();
}
private Shape createTriangle() {
Polygon p = new Polygon();
p.addPoint(0, 20);
p.addPoint(20, 0);
p.addPoint(20, 40);
return p;
}
private Shape createRTriangle() {
Polygon p = new Polygon();
p.addPoint(20, 20);
p.addPoint(0, 0);
p.addPoint(0, 40);
return p;
}
}
If you compile this, you can see that my JButton is too far to the left. How can I move it to the right?
The basic problem with those buttons is that the button is very wide and the visual indicator is to the left. Put a border around them and it becomes obvious.
OTOH I would use an entirely different approach, using text for the buttons and a factory method to make them look as expected.
import java.awt.*;
import javax.swing.*;
public class CustomPointerButtons {
JPanel ui;
CustomPointerButtons() {
initUI();
}
private final void initUI() {
ui = new JPanel(new BorderLayout(4, 4));
JPanel topPanel = new JPanel(new BorderLayout(4, 4));
ui.add(topPanel, BorderLayout.PAGE_START);
ui.add(new JButton("Mister Mix")); //will default to CENTER
topPanel.add(new JLabel("Blah, Blah.."));
JButton back = getMinimalButton(new String(Character.toChars(9668)));
topPanel.add(back, BorderLayout.LINE_START);
JButton forward = getMinimalButton(new String(Character.toChars(9658)));
topPanel.add(forward, BorderLayout.LINE_END);
}
public JButton getMinimalButton(String text) {
JButton b = new JButton(text);
b.setFont(b.getFont().deriveFont(40f));
b.setMargin(new Insets(0,0,0,0));
b.setContentAreaFilled(false);
b.setBorder(null);
return b;
}
public final JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Custom Pointer Buttons");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(new CustomPointerButtons().getUI());
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
The problem is your random preferred size doesn't represent the real size of the triangle.
You can do something like:
public Dimension getPreferredSize() {
//return new Dimension(200, 100);
Rectangle bounds = triangle.getBounds();
return new Dimension(bounds.width, bounds.height);
}
You still have other problems because you will still have painting artifacts. You should always invoke super.paintComponent() when you override the method:
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).fill(triangle);
}
However, this still doesn't really work because the button does other painting as well. So the real problem is that you should not be trying to do custom painting of the button. What you really want to do is custom painting of an Icon. Then you can just add the Icon to the button.
You may want to check out Playing With Shapes. You can use the ShapeIcon class to create your icons. This will provide a more flexible solution since I'm guess all shapes are not represented by an ascii character.
I'm trying to display a message in a JPanel.
I've used the drawString() function of the Graphics class.
Here's my code :
public class Frame {
JFrame frame;
JPanel panel;
Graphics graph;
Frame() {
frame = new JFrame();
panel = new JPanel();
frame.setTitle("My wonderful window");
frame.setSize(800, 600);
frame.ContentPane(panel);
frame.setVisible(true);
}
void displayMessage(String message) {
graph = new Graphics();
graph.drawString(message, 10, 20);
}
}
I've this error :
error: Graphics is abstract; cannot be instantiated
Override the JPanel's paintComponent(Graphics g) method. IN the method you have access to a valid Graphics instance. The method called on each paint.
But may be it's better to add a JLabel to the panel. The label initially has no text and when you have a message just call setText(messageText) of the label.
You should create subclasses for your JFrame and JPanel, and override the methods you want. You could try something like:
package test;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Frame extends JFrame {
public static final String message = "HELLO WORLD!!!";
public class Panel extends JPanel {
public void paintComponent(Graphics graph) {
graph.drawString(message, 10, 20);
}
}
public Frame() {
Panel panel = new Panel();
this.setTitle("My wonderful window");
this.setSize(800, 600);
this.setContentPane(panel);
this.setVisible(true);
}
public static void main(String[] args) {
new Frame();
}
}
Also, there are a lot of great books/tutorials about this. You should read one.
Edit:
You should also read about all the JComponents (JButtons, JLabels...). They're rather useful.