So I'm trying to animate(draw different png image file continuously) on JPanel but if I run this JPanel, there is only white screen.
And I'm trying to draw BufferedImage on the JPanel
public void run() {
try {
while (true) {
if (GAME_STATE) {
..................
}
getContentPane().repaint();
getContentPane().revalidate();
Thread.sleep(GAME_SPEED);
}
} catch (Exception e) {
}
}
This is run method which calls repaint() and revalidate()
public class Panel_Game extends JPanel {
private static final long serialVersionUID = 1L;
Panel_Game() {
// set a preferred size for the custom panel.
this.setPreferredSize(new Dimension(f_width, f_height + 100));
this.setVisible(true);
this.setLayout(null);
this.setDoubleBuffered(true);
this.setFocusable(true);
this.requestFocus(true);
}
#Override
public void paint(Graphics g) {
buffImage = createImage(f_width, f_height + 100);
buffg = buffImage.getGraphics();
getContentPane().revalidate();
super.paintComponent(g);
Draw_Background();
Draw_Player();
Draw_Weapon();
Draw_Enemy();
Draw_EnemyWeapon();
Draw_Item();
.............
g.drawImage(buffImage, 0, 0, this);
}
}
And this is a class that I try to draw image on
public void Game_InterFace() {
JLabel Label_Menu_Board = new JLabel();
JLabel Label_AP_Board = new JLabel();
JLabel Label_Save_Board = new JLabel();
JLabel Label_Load_Board = new JLabel();
Panel_Game panel_Game = new Panel_Game();
panel_Game.addKeyListener(this);
.............................................
.............................................
panel_Game.add(btn_Menu);
panel_Game.add(btn_AP);
panel_Game.add(label_Status);
getContentPane().add(panel_Game);
getContentPane().repaint();
}
.......
public Game_main() {
start();
setLocation(0, 0);
setUndecorated(true);
setSize(f_width, f_height);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = getContentPane();
contentPane.setLayout(null);
Game_Home();
}
Related
here's my problem : I display an ArrayList of JLabel with image and a JPanel with buttons inside a JPanel and I want to display my JPanel above my JLabel when I press a button. But when I press the button, my JPanel is under the JLabels.
Please don't tell me to use a JLayerPane cause if I can do without it it would be best.
Thanks for your solutions.
Here's an exemple of my code :
To run this put the image 100x100 found here :
http://www.html5gamedevs.com/topic/32190-image-very-large-when-using-the-dragging-example/
in a file named image
Main :
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("test");
frame.setSize(900,700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
JPanelControler ctrl = new JPanelControler();
frame.add(ctrl.getMyJpanel());
frame.setVisible(true);
}
}
MyJPanelControler :
public class JPanelControler {
private MyJPanel myJpanel;
public JPanelControler() {
myJpanel = new MyJPanel();
myJpanel.createJLabel();
myJpanel.getButton().addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myJpanel.displayJPanel();
}
});
}
public MyJPanel getMyJpanel() {
return myJpanel;
}
}
MyJPanel :
public class MyJPanel extends JPanel {
private JButton button;
private ArrayList<JLabel> labels;
//a JPanel that contains buttons,... I won't put this class here
private JPanel panel;
public MyJPanel() {
setLayout(null);
button = new JButton("X");
button.setBounds(600,600,50,50);
add(button);
}
public void createJLabel() {
labels = new ArrayList<>();
JLabel label;
try {
BufferedImage image = ImageIO.read(new File("images/image.jpg"));
for(int i=0; i<2; i++) {
label = new JLabel(new ImageIcon(image));
label.setBounds(i*100,50,image.getWidth(), image.getHeight());
labels.add(label);
add(label);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void displayJPanel() {
panel = new JPanel();
panel.setLayout(null);
JButton b = new JButton("Ok");
b.setBounds(0,0,100, 50);
JButton b2 = new JButton("Cancel");
b2.setBounds(0,50,100, 50);
panel.setBounds(150,50, 100, 100);
panel.add(b);
panel.add(b2);
add(panel);
refresh();
}
public void refresh() {
invalidate();
revalidate();
repaint();
}
public JButton getButton() {return this.button; }
}
If you want the buttons to appear over plain images, then you have one of two options:
Draw the images in a paintComponent override in the main JPanel and not as ImageIcons within a JLabel. This will allow you to add components to this same JPanel, including buttons and such, and the images will remain in the background. If you go this route, be sure to call the super.paintComponent(g); method first thing in your override.
Or you could use a JLayeredPane (regardless of your not wanting to do this). You would simply put the background JPanel into the JLayeredPane.DEFAULT_LAYER, the bottom layer (constant is Integer 0), and place the newly displayed JButton Panel in the JLayeredPane.PALETTE_LAYER, which us just above the default. If you go this route, be sure that the added JPanel is not opaque, else it will cover over all images completely.
For an example of the 2nd suggestion, please see below:
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
public class JPanelControler {
private MyJPanel myJpanel;
public JPanelControler() {
myJpanel = new MyJPanel();
myJpanel.createJLabel();
myJpanel.getButton().addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myJpanel.displayJPanel();
}
});
}
public MyJPanel getMyJpanel() {
return myJpanel;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("test");
frame.setSize(900, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
JPanelControler ctrl = new JPanelControler();
frame.add(ctrl.getMyJpanel());
frame.setVisible(true);
}
}
class MyJPanel extends JLayeredPane {
private static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia"
+ "/commons/thumb/f/fc/Gros_Perr%C3%A9.jpg/100px-Gros_Perr%C3%A9.jpg";
private JButton button;
private ArrayList<JLabel> labels;
// a JPanel that contains buttons,... I won't put this class here
private JPanel panel;
public MyJPanel() {
setLayout(null);
button = new JButton("X");
button.setBounds(600, 600, 50, 50);
add(button, JLayeredPane.DEFAULT_LAYER); // add to the bottom
}
public void createJLabel() {
labels = new ArrayList<>();
JLabel label;
try {
URL imgUrl = new URL(IMG_PATH); // ** added to make program work for all
BufferedImage image = ImageIO.read(imgUrl);
for (int i = 0; i < 2; i++) {
label = new JLabel(new ImageIcon(image));
label.setBounds(i * 100, 50, image.getWidth(), image.getHeight());
labels.add(label);
add(label);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void displayJPanel() {
panel = new JPanel();
panel.setLayout(null);
panel.setOpaque(false); // ** make sure can see through
JButton b = new JButton("Ok");
b.setBounds(0, 0, 100, 50);
JButton b2 = new JButton("Cancel");
b2.setBounds(0, 50, 100, 50);
panel.setBounds(150, 50, 100, 100);
panel.add(b);
panel.add(b2);
add(panel, JLayeredPane.PALETTE_LAYER); // add it above the default layer
refresh();
}
public void refresh() {
// invalidate(); // not needed
revalidate();
repaint();
}
public JButton getButton() {
return this.button;
}
}
I'm not sure why my JButton is not displaying when I add it to the JPanel class: if my class extends JPanel, shouldn't this.add be sufficient? And if I remove this Jpanel class from another Jpanel, the components attached to this panel should disappear as well right? Thank you!
public class Menu extends JPanel{
private static final long serialVersionUID = 1L;
static boolean startGame = false;
public static String user;
public Menu(final JFrame frame) {
JPanel userName = new JPanel(); // create new JPanel
final JTextField text = new JTextField();
text.setText("input your username here");
//adds userName input box to the panel
Action action = new AbstractAction(){
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
user = text.getText();
text.setVisible(false);
Menu.startGame = true;
}};
text.addActionListener(action);
userName.add(text);
frame.add(userName, BorderLayout.SOUTH);
frame.revalidate();
frame.repaint();
setFocusable(true);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
sndMenu newMenu = new sndMenu(frame);
newMenu.setVisible(true);
}
});
/**
* this does not display help!
*/
//add a button to the menu called "help"
JButton help = new JButton("get instructions");
this.add(help,BorderLayout.CENTER);
help.setVisible(true);
help.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
instructions instr = new instructions(frame);
frame.add(instr);
frame.revalidate();
frame.repaint();
}
});
}
public void paint (Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
Font fnt0 = new Font("Manaspace", Font.BOLD, 40);
Font fnt1 = new Font("Manaspace", Font.BOLD, 30);
g.setFont(fnt0);
g.setColor(Color.white);
g.drawString("Welcome To Jumping Box!", 120, 300);
g.setFont(fnt1);
g.drawString("Click to play!", 260, 400);
}
}
I have a desktop application in swing. I have a JPanel in which the image as the background and in it two buttons and a JScrollPane as shown in the picture Frame with JPanel. I have a function (showLabel()) which, when JScrollPane the end, add JLabel with transparent images and disappear a few seconds. The problem is that when you add JLabel. JLabel bad shows as seen in Fig Bad shows. Can you help me with my problem?
public class MainWindow {
private JFrame frame;
private PanelPopis panelPopis = new PanelPopis(this);
private MyPaint myPaint;
public MainWindow {
setWindow():
BufferedImage image1 = ImageIO.read(getClass().getClassLoader().getResource("poz.png"));
this.myPaint = new MyPaint(image1);
this.frame.add(myPaint);
this.myPaint.add(panelPopis.setPanel());
}
private void setWindow() {
this.frame = new JFrame("DD");
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.setSize(400, 680);
this.frame.setResizable(false);
this.frame.setLocationRelativeTo(null);
}
private void showLabel(){
JLabel label = new JLabel();
label.setIcon(new ImageIcon(new ImageIcon(getClass().getClassLoader().getResource("postEn.png")).getImage().getScaledInstance(395, 653, Image.SCALE_DEFAULT)));
label.setBackground(new Color(0, 0, 0, 10));
label.setOpaque(true);
this.frame.invalidate();
this.frame.add(label);
this.frame.revalidate();
int delay2 = 3000; // milliseconds
ActionListener taskPerformer2 = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frame.remove(label);
frame.revalidate();
frame.repaint();
}
};
Timer myTimer2 = new Timer(delay2, taskPerformer2);
myTimer2.setRepeats(false);
myTimer2.start();
}
}
public class MyPaint extends JPanel {
private static final long serialVersionUID = 1L;
BufferedImage image;
public MyPaint(BufferedImage image) {
setOpaque(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, 395, 653, this);
}
}
public class PanelPopis extends JPanel {
private static final long serialVersionUID = 7676683627217636485L;
private JButton setLanguage;
private JButton cont;
private JScrollPane scrolPanel;
private JTextArea popis;
private MainWindow mainWindow;
public PanelPopis(MainWindow mainWindow) {
this.mainWindow = mainWindow;
}
public JPanel setPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setOpaque(false);
JPanel panel2 = new JPanel();
Border border = panel2.getBorder();
Border margin = new EmptyBorder(0, 0, 4, 0);
panel2.setBorder(new CompoundBorder(border, margin));
panel2.setOpaque(false);
panel2.add(this.scrolPanel = new JScrollPane(popis));
panel.add(this.setLanguage = new JButton("language settings"), BorderLayout.NORTH);
panel.add(this.cont = new JButton("CONTINUE"), BorderLayout.SOUTH);
panel.add(panel2, BorderLayout.CENTER);
return panel;
}
}
I would suggest to use the getResource() method instead of the getResourceAsStream() and have the path of both images inputted there this way.
The classLoader could behave differently (in your case due to the differences between the two OS's) so doing it this way would guarantee that you application is always getting the correct resources.
More on the getResource here:
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
well I've had a few tips on using the splitpane to split my frame into two areas, but I can't manage to get it to show something useful. The code looks as follows:
public class Whiteboard extends JPanel {
int width = 600;
int sidePanelWidth = 200;
int lineHeight = 120;
int numberOfLines = 5;
JFrame frame = null;
Glyph glyph = null;
//java.awt.Rectangle bounds = new java.awt.Rectangle();
Bounds bounds = null;
JSplitPane splitPane = null;
JPanel tools = null;
public Whiteboard() {
frame = new JFrame();
frame.setSize(width + sidePanelWidth, getFullHeight());
FlowLayout simpleLayout = new FlowLayout();
frame.setLayout(simpleLayout);
tools = new JPanel();
tools.setSize(new Dimension(sidePanelWidth, getFullHeight()));
this.setSize(width, getFullHeight());
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this, tools);
splitPane.setPreferredSize(new Dimension(width + sidePanelWidth, getFullHeight()));
splitPane.setOneTouchExpandable(false);
splitPane.setDividerLocation(150);
frame.add(splitPane);
this.setBackground(Color.white);
java.awt.Rectangle rectBounds = this.getBounds();
bounds = new Bounds((int)rectBounds.getX(), (int)rectBounds.getY(), (int)(rectBounds.getX() + rectBounds.getWidth()), (int)(rectBounds.getY() + rectBounds.getHeight()));
}
public int getFullHeight() {
return lineHeight * numberOfLines;
}
I changed now the code like this:
public static void main(String[] args) {
int sidePanelWidth = 200;
JFrame frame = new JFrame();
Whiteboard whiteboard = new Whiteboard();
JPanel sidePanel = new JPanel();
sidePanel.setPreferredSize(new Dimension(sidePanelWidth, whiteboard.getFullHeight()));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.add(whiteboard, JSplitPane.LEFT);
splitPane.add(sidePanel, JSplitPane.RIGHT);
frame.setLayout(new FlowLayout());
frame.getContentPane().add(splitPane);
frame.pack();
frame.setVisible(true);
whiteboard.repaint();
}
And the constructor to this:
public Whiteboard() {
this.setPreferredSize(new Dimension(width, getFullHeight()));
this.setBackground(Color.red);
}
Now I don't know where the problem is, maybe it's because it doesn't call the paintComponent method. I tried forcing it by calling repaint() it doesn't help, it just doesn't call this componenent
Edit: Well now it seems it is calling the paintComponent method after all, but still I get the screen like this:
As you can see, it's not looking so good. Well the code of my current main Method:
public static void main(String[] args) {
int sidePanelWidth = 200;
JFrame frame = new JFrame();
Whiteboard whiteboard = new Whiteboard();
JPanel sidePanel = new JPanel();
sidePanel.setPreferredSize(new Dimension(sidePanelWidth, whiteboard.getFullHeight()));
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.add(whiteboard, JSplitPane.LEFT);
splitPane.add(sidePanel, JSplitPane.RIGHT);
frame.setLayout(new FlowLayout());
frame.getContentPane().add(splitPane);
frame.pack();
frame.setVisible(true);
whiteboard.repaint();
}
Any idea how to change it to fix the problem? Do I need to post other methods?
Creating a JFrame from within the constructor of a JPanel should really not be done.
Here is an example I created:
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.*;
public class JavaApplication100 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication100().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
private void initComponents(Container contentPane) {
JPanel mainPanel = new JPanel();
//create our 2 seperate panels (could be custom ones)
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
//add labels for viewing
leftPanel.add(new JLabel("LEFT"));
rightPanel.add(new JLabel("RIGHT"));
//just so you can see em or they would be small
leftPanel.setPreferredSize(new Dimension(300, 300));
rightPanel.setPreferredSize(new Dimension(300, 300));
JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
//add panels to split pane
jsp.add(rightPanel, JSplitPane.RIGHT);
jsp.add(leftPanel, JSplitPane.LEFT);
mainPanel.add(jsp);//add splitpane to mainpanel
contentPane.add(mainPanel);
}
}
EDIT/UPDATE:
as per your comment if you want to colour the background override paintComponent(Graphics g) in your WhiteBoard which extendsJPanel like so:
public class WhiteBoard extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(0, 0, getWidth(), getHeight());
}
}
You could use JSplitPane.setDividerLocation(int) instead...
public class TestSplitPane extends JFrame {
public TestSplitPane() throws HeadlessException {
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(new BorderLayout());
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(new JLabel("I'm on the left"));
splitPane.setRightComponent(new JLabel("I'm on the right"));
add(splitPane);
splitPane.setDividerLocation(200);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
new TestSplitPane().setVisible(true);
}
});
}
}
I have a JPanel which contains 2 more JPanel. Located on the left(leftBox) and the right(rB), I wanted to add a background image on the right JPanel (rB).
But the result I get is
http://i.imgur.com/tHz1x.jpg
the result I wanted
http://i.imgur.com/xHbpx.jpg
public void paintComponent(Graphics g)
{
//this.paintComponent(g);
if(wdimage != null) g.drawImage(wdimage,0,0,800,800,rB); //(image,location x, location y, size x, size y)
}
The rB Panel is blocking the image, what I want is to display the image on the JPanel, and add some jlabels and text field on top of the JPanel and image later on.
Here it's appearing without any problems, have a look :
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class PanelExample
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Panel Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBorder(
BorderFactory.createMatteBorder(
5, 5, 5, 5, Color.WHITE));
contentPane.setBackground(Color.WHITE);
contentPane.setLayout(new BorderLayout(10, 10));
ImagePanel imagePanel = new ImagePanel();
//imagePanel.createGUI();
BlankPanel blankPanel = new BlankPanel();
contentPane.add(blankPanel, BorderLayout.LINE_START);
contentPane.add(imagePanel, BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PanelExample().createAndDisplayGUI();
}
});
}
}
class ImagePanel extends JPanel
{
private BufferedImage image;
public ImagePanel()
{
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
try
{
image = ImageIO.read(new URL("http://gagandeepbali.uk.to/gaganisonline/images/background.jpg"));
}
catch(Exception e)
{
e.printStackTrace();
}
createGUI();
}
public void createGUI()
{
setLayout(new GridBagLayout());
JPanel loginPanel = new JPanel();
loginPanel.setOpaque(false);
loginPanel.setLayout(new GridLayout(2, 2, 2, 2));
JLabel userLabel = new JLabel("USERNAME : ");
userLabel.setForeground(Color.WHITE);
JTextField userField = new JTextField(10);
JLabel passLabel = new JLabel("PASSWORD : ");
passLabel.setForeground(Color.WHITE);
JPasswordField passField = new JPasswordField(10);
loginPanel.add(userLabel);
loginPanel.add(userField);
loginPanel.add(passLabel);
loginPanel.add(passField);
add(loginPanel);
System.out.println("I am finished");
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
class BlankPanel extends JPanel
{
public BlankPanel()
{
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
setBackground(Color.WHITE);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(100, 300));
}
}