so I remember about 2 years ago I had an issue with displaying an icon on a label on a mac.
I've tried to do it again this year whilst working on a project and still have the same issue. Could anyone check my code works on a different computer? Either mac or windows just so I know the code works and also if anyone has any idea why it doesn't work on mine let me know!
All that happens is the frame appears with the text and buttons but no background image.
public class MemoryRoom extends JPanel {
/** Background image of the menu screen */
private Image bg = new ImageIcon("memoryRoom.jpg").getImage();
/** JFrame used in the entire game */
protected JFrame app;
public MemoryRoom(JFrame app) {
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
app.setSize(1150, 680);
this.app = app;
initialize();
app.repaint();
}
protected void initialize() {
//final JPanel menuScreenPanel = new JPanel();
setVisible(true);
setSize(1150, 680);
setLayout(null);
JLabel lblSelectGame = new JLabel("Please select the game you wish to play:");
lblSelectGame.setBounds(320, 180, 600, 50);
add(lblSelectGame);
lblSelectGame.setFont(new Font("Dialog", Font.BOLD, 24));
lblSelectGame.setForeground(Color.WHITE);
JButton btnSnakesAndLadders = new JButton("Snakes and Ladders");
btnSnakesAndLadders.setBounds(370, 250, 200, 45);
add(btnSnakesAndLadders);
JButton btnDansCrazyTic = new JButton("Dan's Crazy Tic Tac Toe");
btnDansCrazyTic.setBounds(590, 250, 200, 45);
add(btnDansCrazyTic);
btnDansCrazyTic.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent TicTacToeEvent) {
setVisible(false);
}
});
btnSnakesAndLadders.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent SnakesAndLaddersEvent) {
setVisible(false);
}
});
app.getContentPane().add(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bg, 0, 0, 1150, 680, this);
}
public static void main (String args []){
new MemoryRoom(new JFrame());
}
}
Related
This question is an extension of java- repaint() method is misbehaving?
(Reading it, is optional)
I am working on a Music Player
I am using a JSlider as seek bar and using a JLabel to draw text on screen, such as song name.
I am new to Graphics2D
Here's the minimized code:
public class JSliderDemo extends JFrame
{
JLabel label;
JSlider seek = new JSlider();
int y = 10;
public JSliderDemo()
{
setSize(400, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
createWindow();
setVisible(true);
startThread();
}
public void createWindow()
{
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(true);
panel.setBackground(Color.BLUE);
panel.setBorder(new LineBorder(Color.YELLOW));
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
label = new Component();
label.setSize(300, 300);
createSlider();
layeredPane.add(seek, new Integer(50));
layeredPane.add(label, new Integer(100));
panel.add(layeredPane);
add(panel);
}
protected void createSlider()
{
seek.setUI(new SeekBar(seek, 300, 10, new Dimension(20, 20), 5,
Color.DARK_GRAY, Color.RED, Color.RED));
seek.setOrientation(JProgressBar.HORIZONTAL);
seek.setOpaque(false);
seek.setLocation(10, 50);
seek.setSize(300, 20);
seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
seek.setMinimum(0);
seek.setMaximum(1000);
seek.setBorder(new MatteBorder(5, 5, 5, 5, Color.CYAN));
}
protected void startThread()
{
Thread thread = new Thread(new Runnable(){
#Override
public void run()
{
try
{
while(true)
{
if(y == label.getHeight()){y = 1;}
label.repaint();
y += 1;
Thread.sleep(100);
}
}
catch(Exception ex){}
}
});
thread.start();
}
protected class Component extends JLabel
{
#Override
public void paintComponent(Graphics g)
{
Graphics2D gr = (Graphics2D) g;
gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gr.setColor(Color.RED);
gr.setFont(new Font("Calibri", Font.PLAIN, 16));
gr.drawString("Song Name", 50, y);
gr.dispose();
}
}
public static void main(String[] args)
{
new JSliderDemo();
}
}
The problem is, when I call repaint() for JLabel it automatically repaints JSlider with it even though JSlider is not included in JLabel.
Output :
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted
Slider re-painted.........
Now if I remove label.repaint() from the Thread, then the JSlider is not re-painted.
Output:
Slider re-painted
Slider re-painted
Is the repaint() method supposed to work like this?
In my last question, I was told to use Layout Manager and when I did use GridLayout just for checking if it's the solution, then it worked!
Only JLabel was repainted.
But I want to overlap JLabel on JSlider, so I thought of using JLayeredPane. And now, the problem is back.
How can I solve this?
Bottom Line : How can I overlap JLabel on JSlider without leading to repaint() method misbehave ?
OR
Does the repaint() method work like this?
As was already mentioned in the comments, the reason for your JSlider being repainted is that it has overlapping bounds with the JLabel. Even though your label doesn't paint over the area of the slider swing will still mark the overlapping area as dirty (i.e. the overlapping part of the slider will need to be repainted) because swing doesn't know that you are only painting in one part of the component.
To reduce the amount of repaints you will need to make the size of your JLabel smaller. Preferably only as large as it needs to be by invoking its getPreferredSize() method. You'll then be able to move the text by moving the location of the label.
Also you shouldn't be doing updates to the gui in a plain Thread. Use javax.swing.Timer instead. It ensures that all updates to the gui happen on the swing event thread, which is where they should be made.
After making these adjustments to your code the slider is only repainted while the label is actually visually over the slider.
public class JSliderDemo extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(JSliderDemo::new);
}
private final JLabel label = new CustomLabel();
public JSliderDemo() {
setSize(400, 400);
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
createWindow();
setVisible(true);
startTimer();
}
public void createWindow() {
JPanel panel = new JPanel(new BorderLayout());
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
label.setLocation(0, 0);
label.setBorder(new LineBorder(Color.RED));
label.setSize(label.getPreferredSize());
layeredPane.add(createSlider(), Integer.valueOf(50));
layeredPane.add(label, Integer.valueOf(100));
panel.add(layeredPane);
setContentPane(panel);
}
protected JSlider createSlider() {
JSlider seek = new CustomSlider();
seek.setOrientation(JProgressBar.HORIZONTAL);
seek.setOpaque(false);
seek.setLocation(10, 50);
seek.setSize(300, 20);
seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
seek.setMinimum(0);
seek.setMaximum(1000);
seek.setBorder(new LineBorder(Color.BLUE));
return seek;
}
private void startTimer() {
new Timer(100, e -> {
int y = label.getY();
int maxY = label.getParent().getHeight();
if (y == maxY) {
y = -label.getHeight();
}
label.setLocation(label.getX(), y + 1);
label.repaint();
}).start();
}
private static class CustomLabel extends JLabel {
protected CustomLabel() {
setFont(new Font("Calibri", Font.PLAIN, 16));
setText("Song Name");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Painting Label");
}
}
protected static class CustomSlider extends JSlider {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Painting Slider");
}
}
}
My question is how to display buttons on top of a circle which created with Graphics. My code is :
public class Grafik extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Grafik frame = new Grafik();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Grafik() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 784, 419);
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnNewButton = new JButton("Click");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fire();
}
});
btnNewButton.setBounds(64, 73, 32, 32);
contentPane.add(btnNewButton);
}
public void fire()
{
JPanel panel = new JPanel(){
#Override
public void paint(Graphics g)
{
g.setColor(Color.black);
g.drawOval(20, 20, 400, 400);
g.fillOval(20,20,400,400);
g.setColor(Color.white);
g.drawOval(60, 60, 300, 300);
g.fillOval(60,60,300,300);
}
};
panel.setBounds(10, 27, 383, 233);
setContentPane(panel);
JButton btn = new JButton();
btn.setIcon(new ImageIcon("C:\\Users\\nuria\\Desktop\\icon1.png"));
btn.setBounds(75, 76, 32, 32);
panel.add(btn);
}
}
This code is a little part of my project. I have a lot of panels in my project and my fire method isn't called firstly. I mean the fire method is called by sixth panel. I have to draw two circles with buttons. These buttons should be between two circles. But i cant display buttons directly. When i hover the buttons, they show. I want to show buttons instantly when the sixth panel opens.
I have two buttons above. When the first button is clicked, another panel should open and show circles(which created with Graphics) and another button(with a icon) between them.
JPanel panel = new JPanel(){
#Override
public void paint(Graphics g)
{
Don't override paint(). Custom painting is done by overriding paintComponent() and don't forget to invoke super.paintComponent() as the first statement.
The problem with your current code is that by overriding paint you have changed the default painting logic of the panel and the child components are never painted.
Take a look at the section from the Swing tutorial on Custom Painting for more information and examples, especially the section on A Closer Look at the Paint Mechanism.
I am working on a little menu program with clickable buttons and an image that changes based on button clicks. If I click a button I get a shadow of the button at the bottom where I change the JLabel text. I cannot figure it out for the life of me. Any advice would be greatly appreciated. Visuals below...thanks
public class SampleGUI
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
System.out.println("Created GUI on EDT? " +
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Robert's VICI Prototype");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}
class MyPanel extends JPanel
{
// Fields
Image imageDisplayed;
JLabel status;
// Methods
public MyPanel()
{
setBorder(BorderFactory.createLineBorder(Color.BLACK));
setLayout(null);
JLabel title = new JLabel("CS380 TEAM 5 VICI Prototype");
title.setFont(new Font("Tahoma", Font.BOLD, 20));
title.setBounds(425, 10, 400, 40);
add(title);
status = new JLabel("Please click an option above.");
status.setFont(new Font("Tahoma", Font.BOLD, 14));
status.setBounds(425, 740, 400, 40);
add(status);
JButton choice1 = new JButton("Search Class");
choice1.setBounds(50, 50, 150, 40);
add(choice1);
JButton choice2 = new JButton("Add Class");
choice2.setBounds(225, 50, 150, 40);
add(choice2);
JButton choice3 = new JButton("Drop Class");
choice3.setBounds(400, 50, 150, 40);
add(choice3);
JButton choice4 = new JButton("Verify Reg Hold");
choice4.setBounds(575, 50, 150, 40);
add(choice4);
JButton choice5 = new JButton("Verify Reg Date");
choice5.setBounds(750, 50, 150, 40);
add(choice5);
JButton choice6 = new JButton("Schedule Advisor");
choice6.setBounds(925, 50, 150, 40);
add(choice6);
choice6.addActionListener(
new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Schedule Advisor button pressed.");
status.setText("Choose a date.");
imageDisplayed = new ImageIcon("C:\\Temp\\sa01.jpg").getImage();
}
});
JButton exit = new JButton("EXIT");
exit.setBounds(940, 750, 150, 40);
add(exit);
exit.addActionListener(
new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
imageDisplayed = new ImageIcon("C:\\Temp\\main.jpg").getImage();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(1100, 800);
}
#Override
public void paintComponent(Graphics g)
{
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
}
You've broken the paint chain...
#Override
public void paintComponent(Graphics g)
{
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
The first thing you should be calling is super.paintComponent(g)
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(imageDisplayed, 100, 120, 900, 600, this);
}
The Graphics context is shared resource, meaning that the Graphics context you get has also been used to paint the other components that have also been painted. One of the jobs of paintComponent is to clear the Graphics context ready for the component to be painted (fill the background)
See Painting in AWT and Swing and Performing Custom Painting for more details
You should, also, avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify. See Why is it frowned upon to use a null layout in SWING? for more details...
Before you go all defensive over getting your screen laid out just nicely, you shouldn't be doing it this way. You controls should be laid out on separate containers (using appropriate layout managers) and you "drawing surface" should be it's own component. See Laying Out Components Within a Container for more details...
If you're still not convicned, take a look at Why setting setPreferredSize() on JFrame is bad? and java expandable JDialog for examples of differences between Mac and Windows
I m creating a GUI in java and would like to use a JTextArea, however I am having a lot of trouble adding it to the frame. How would I go about creating a text Area and then using it to read text or display text?
Here is my GUI code so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class addMemoUI extends JFrame {
JFrame frame = new JFrame();
/**
* Create the application.
*/
public addMemoUI() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame.getContentPane().setBackground(new Color(255, 255, 255));
frame.getContentPane().setLayout(null);
JButton button = new JButton("Create");
button.setBackground(new Color(100, 149, 237));
button.setBounds(135, 350, 130, 50);
frame.getContentPane().add(button);
JLabel lblMemos = new JLabel("MEMOS");
lblMemos.setForeground(new Color(100, 149, 237));
lblMemos.setFont(new Font("Moire", Font.BOLD, 30));
lblMemos.setBounds(22, 21, 234, 37);
frame.getContentPane().add(lblMemos);
JButton button_1 = new JButton("Cancel");
button_1.setBackground(new Color(100, 149, 237));
button_1.setBounds(5, 350, 130, 50);
frame.getContentPane().add(button_1);
frame.setBounds(100, 100, 270, 400);
frame.setUndecorated(true); //REMOVES MENU BAR
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnExit = new JButton("");
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MemoUI window = new MemoUI();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Thanks very much :)
Here is example for how to use JTextArea. You can set, get or append text. You can find the others by google.
public class Example {
private JTextArea jtextbox;
private void initialize() {
JFrame frm = new JFrame();
:
JScrollPane scroll = new JScrollPane();
jtextbox= new JTextArea();
scroll.setViewportView(jtextbox); // add scroll panel
jtextbox.setTabSize(4);
jtextbox.setLineWrap(true);
jtextbox.setBackground(SystemColor.window);
}
private void setText(String text) {
jtextbox.append(text); // or setText(text)
}
private String getText() {
return jtextbox.getText();
}
}
I am trying to make a program to java and i have the common problem with flickering. I have try many things to eliminate but all the same. while the oval that i paint is moving the japplet is flickering. i need your help to solve this problem. here is my code:
import java.awt.Color;
public class all extends JApplet implements Runnable {
double x=0;
double y=0;
int m=0;
int n=0;
int f=30;
int μ=0;
Thread kinisi;
JPanel panel;
JFrame frame;
private boolean running = false;
private JTextField textField1;
private JTextField textField2;
Image backGround;
JPanel panel_3;
Image bf = createImage(m, n);
private Graphics doubleg;
private Image i;
public void init() {
this.setSize(800, 700);
}
public all() {
getContentPane().setLayout(null);
JButton btnNewButton = new JButton("Start");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String b=textField2.getText();
String z =textField1.getText();
if (textField1.getText().equals("") ||
textField2.getText().equals("")){
JOptionPane.showMessageDialog(
new JFrame(),
"Δωστε τιμή για το φ και το μ!",
"ERROR",JOptionPane.ERROR_MESSAGE);
} else{
f = Integer.parseInt(b);
μ = Integer.parseInt(z);
Start(); }
}
});
btnNewButton.setBounds(469, 168, 89, 23);
getContentPane().add(btnNewButton);
JButton btnStop = new JButton("Pause");
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pause();
}
});
btnStop.setBounds(588, 168, 89, 23);
getContentPane().add(btnStop);
JButton btnReset = new JButton("Reset");
btnReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Reset();
}
});
btnReset.setBounds(701, 168, 89, 23);
getContentPane().add(btnReset);
JLabel label = new JLabel("\u03BC");
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setBounds(549, 63, 46, 14);
getContentPane().add(label);
textField1 = new JTextField();
textField1.setBounds(529, 101, 86, 20);
getContentPane().add(textField1);
textField1.setColumns(10);
JLabel label_1 = new JLabel("\u03C6");
label_1.setHorizontalAlignment(SwingConstants.CENTER);
label_1.setBounds(681, 63, 46, 14);
getContentPane().add(label_1);
textField2 = new JTextField();
textField2.setBounds(667, 101, 86, 20);
getContentPane().add(textField2);
textField2.setColumns(10);
JButton btnNewButton_1 = new JButton("");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(
new JFrame(),
"Οδηγίες προγράμματος","Οδηγίες",
JOptionPane.INFORMATION_MESSAGE);
}
});
btnNewButton_1.setIcon(
new ImageIcon(all.class.getResource("/Images/info.png")));
btnNewButton_1.setBounds(732, 5, 39, 35);
getContentPane().add(btnNewButton_1);
JLabel label_2 = new JLabel("");
label_2.setIcon(
new ImageIcon(all.class.getResource("/Images/earth.jpg")));
label_2.setBounds(-20, 0, 820, 361);
getContentPane().add(label_2);
JPanel panel_1 = new JPanel();
panel_1.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_1.setBounds(10, 372, 369, 290);
getContentPane().add(panel_1);
JPanel panel_2 = new JPanel();
panel_2.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_2.setBounds(408, 372, 369, 290);
getContentPane().add(panel_2);
}
public void paint(Graphics g){
super.paint(g);
g.drawLine(0,f,350,200);
g.drawLine(0,200,350,200);
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
//Graphics2D g2d = (Graphics2D) g;
g.drawLine(460,400,460,650);
g.drawLine(20, 620, 350, 620);
g.drawLine(50,400,50,650);
g.drawLine(430, 620, 760, 620);
}
public void Start() {
kinisi = new Thread(this);
kinisi.start();
running = true;
}
public void run() {
while (running) {
if (x < 340){
double l = 200-f;
double k = l/350;
double y=k*x+f-30;
x= x+1;
m = (int) x;
n = (int) y;
repaint();
try {
Thread.sleep(μ);
} catch (InterruptedException ie) {}
}
}
}
public void update(Graphics g) {
if(i==null){
i=createImage(800,700);
doubleg = i.getGraphics();
}
doubleg.setColor(getBackground());
doubleg.fillRect(0,0,800,700);
doubleg.setColor(getForeground());
paint(doubleg);
g.drawImage(i,0,0,this);
}
public void paint1(Graphics g){
g.drawLine(0, f ,350, 200);
g.drawOval(m, n, 40, 40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
}
public void pause() {
if (kinisi != null) {
running = false;
}
}
public boolean Reset() {
if (kinisi != null) {
running = false;
kinisi.interrupt();
kinisi = null;
x=0;
y=0;
f=30;
m=0;
n=0;
repaint();
textField1.setText("");
textField2.setText("");
}
Graphics g = getGraphics();
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
return false;
}
public static void main(String[] args) {
JFrame frame = new JFrame("FISIKI");
frame.getContentPane().add(new all());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
frame.setResizable(false);
}
}
Thank you very much and sorry for my english are not very good!
There are a number of things that jump out at me.
You're extending from JApplet, but are adding it to a JFrame
You're mixing components with you custom painting
Not using layout managers.
Using getGraphics.
Firstly...
You should never override paint of a top level container (like JApplet). There are many reasons and you've found one. Top level containers are not double buffered. Instead, you should be creating a custom component (by extending something like JPanel) and overriding it's paintComponent method...
Secondly
Decided how you application is going to be. Is it an applet or application? If you follow the first point, then it really doesn't matter, as you only simply need to add the panel to the top level container.
Thirdly
I would create a panel that did the custom painting. Then I would create separate containers for all the fields and other parts of the application. This will allow you to separate the areas of responsibility. It would also allow you to use layout managers ;)
Fourthly
Use layout managers. The layout manager API has being designed to solve one of this most annoying aspects of GUI design, you're asking for a lot of trouble and work you decided to discard it - IMHO.
Fifthly
getGraphics should never be used. Apart from the fact that it can return null, it is only a snap shot of what is currently on the screen. As soon as the RepaintManager decides to perform a repaint, anything rendered to it will be lost. You should use paintComponent to update the state of your custom pane.