After a lot of research I only could get that board image with using label. Now I cannot change it's position. I tried a lot of functions. What is the exact function do I need
public class Board extends JFrame {
private ImageIcon image;
private JLabel label;
public Board() {
image = new ImageIcon(getClass().getResource("board.png"));
label = new JLabel(image);
label.setLocation(200, 0); //This is the one that I expected to do the thing
add(label);
}
public static void main(String [] args) {
Board b = new Board();
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.setVisible(true);
b.setSize(1280, 1000);
}
}
Don't try to manually set the location of a component. Swing was designed to be used with layout managers. Read the section from the Swing tutorial on Using Layout Managers for more information.
One way to position a component is to give the component a Border. So you could do something like:
label.setBorder( new EmptyBorder(200, 0, 0, 0) );
The tutorial also has a section on How to Use Borders.
First of all: you shouldn't move components manually. This should be left to the layoutmanager. But you can. The basic problem you're facing is - or atleast i think so - : you're board still has an layoutmanager set, which will continue to layout the board and due to this aswell move (and handle the size of) you're component. Just call setLayout(null); before positioning the label and specify the size and it should work.
Related
Modifiers.java:
package game;
import java.awt.*;
import java.io.*;
import javax.swing.*;
public class Modifiers extends Data{
public static void setupJcomponents(){
frame.setUndecorated(true);
frame.setSize(MW,MH);
frame.setResizable(false);
frame.setVisible(true);
frame.setLayout(null);
for(int btn=0; btn<4; btn++) {
Buttons[btn] = new JPanel();
Buttons[btn].setBounds(btn*100,0,100,100);
Buttons[btn].setVisible(true);
Buttons[btn].setBackground(new Color(btn*50,btn*50,btn*50));
frame.getContentPane().add(Buttons[btn]);
}
menuBackground.setBounds(0,0,MW,MH);
menuBackground.setVisible(true);
menuBackground.setBackground(Color.black);
healthIndicator.setText(String.valueOf(healthValue));
healthIndicator.setFont(new Font("Terminal", Font.PLAIN, 100));
healthIndicator.setBounds(600,600,100,100);
healthIndicator.setForeground(Color.blue);
try{
PixelFont = Font.createFont(Font.TRUETYPE_FONT, new File("PixelFont.ttf"));
} catch (IOException e) {
PixelFont = new Font("Terminal", Font.PLAIN, 100);
} catch(FontFormatException e) {
PixelFont = new Font("Terminal", Font.PLAIN, 100);
}
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(PixelFont);
frame.getContentPane().add(healthIndicator);
frame.getContentPane().add(menuBackground);
}
}
Data.java:
package game;
import java.awt.*;
import javax.swing.*;
public class Data {
// this is where I will declare and alter all variable that will be used
public static JFrame frame = new JFrame();
public static JLabel healthIndicator = new JLabel();
public static JPanel Buttons[] = new JPanel[5];
public static JPanel menuBackground = new JPanel();
public static final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
public static final int MW = (int) screenSize.getWidth();
public static final int MH = (int) screenSize.getHeight();
public static Font PixelFont;
public static int maxHealth = 100;
public static int healthValue = maxHealth;
}
Frame.java:
package game;
public class Frame {
public static void main(String[] args) {
Modifiers.setupJcomponents();
}
}
whenever i rum Frame.java the menu Background disappears and the text altogether stops showing up. but if the path to the .ttf file is wrong it just skips over the font and uses the default instead. How do i get this font to load properly as well as not cause my background background to disappear? I have tried changing the path to the .ttf file and turning various parts of the code into comments, but even if the font of the health indicator is a default font, these errors will still occur, however if i try removing the try-catch loop then the errors aren't there anymore.
There are all kinds of problems with the code. Not exactly sure why the Fonts is causing an issue, but it has something to do with the overall structure of your code and you aren't using Swing the way it was designed to be used.
whenever i rum Frame.java the menu Background disappears and the text altogether stops showing up
What appears to be directly related to the above question is that the setVisible(true) statement should be executed AFTER all the components have been added to the frame. This will make sure all the components are painted.
Note this will still only work by chance because you happen to add the "background" panel to the frame last. Swing paints components in the reverse order that are added to any given panel.
Regarding other problems.
your painting code only works by chance. You should not be adding all your components directly to the frame. Swing is not designed to paint components in 3 dimensions directly when the components overlap one another. Swing is designed to have a parent child relationship. So that would mean you add your "background" panel to the frame. Then you add a panel containing the buttons to the "background" and you add the "health" component to the background.
Related to above you should NOT be using a null layout. Swing was designed to be used with a layout manager. This will make sure components don't overlap. So in your case you can use a BorderLayout for the "background" panel. Then you can add the "buttons" panel to the BorderLayout.PAGE_Start and the "health" component to the `BorderLayout.PAGE_END. This will ensure that the components are at the top/bottom of the background panel.
Don't set the size of the frame. Instead you use the setExtendedState(JFrame.MAXIMIZED_BOTH) property. The frame will be the size of the screen. The "GamePanel" will be take up all the space of the frame. So there is no need to set or use hardcoded values.
Don't use static variables and method. This indicates poor design. What you should be doing is creating a GamePanel class, which would essentially be your background panel. This class would contain the instance variables needed for the game. It would create the "buttons" panel and the "health" component and add it to itself.
Variable names should NOT start with upper case characters.
I have a JScrollPanel and a JPanel added to it. I would like to draw to the JPanel and make the scrollbars of the JScrollPane appear whenever the drawing exceeds the size of the panel and be able to scroll the drawing both vertically and horizontally.
I have tried consulting with various forums and the official docs and tried a few things (setting the borders, the preferred size, etc.) but none seems to yield the desired effects.
I have a JFrame (with GridBagLayout, btw.) :
JFrame frame1 = new JFrame("Application");
frame1.setVisible(true);
frame1.setMinimumSize(new Dimension(580,620));
frame1.setResizable(false);
frame1.setLocationRelativeTo(null);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
The relevant components are :
JPanel panel1 = new JPanel();
JScrollPane scrollPane = new JScrollPane(panel1);
frame1.add(scrollPane, gbc_panel1); //added with layout constraints
JPanel :
panel1.setBackground(Color.BLACK);
panel1.setPreferredSize(new Dimension(500,500));
panel1.setMinimumSize(new Dimension(360,360));
panel1.setMaximumSize(new Dimension(1000,1000));
JScrollPane :
scrollPane.setAutoscrolls(true);
The relevant code from the action event
of a button that does the drawing :
Graphics g;
g = panel1.getGraphics();
panel1.paint(g);
g.setColor(new Color(0,128,0));
/* this is followed by some more code that
does the drawing of a maze with g.drawLine() methods */
The code does the drawing perfectly, I just can't seem to figure it out how to make the scrolling and dynamic resizing happen.
I would appreciate any helpful comments or remarks!
Thank you!
Ultimately rewriting the paint method did the trick as #MadProgrammer suggested. I was just hoping that I could do the painting without having to define my custom JPanel class, but looks like it doesn't work that way.
The custom class looks like this:
class Drawing extends JPanel {
int mazeSize;
public Drawing(JTextField jtf)
{
try {
this.mazeSize = Integer.parseInt(jtf.getText());
}
catch (Exception e)
{
JOptionPane.showMessageDialog(this, "ERROR! Invalid size value!");
}
} // the constructor gets the size of the drawing from a textField
public Dimension getPreferredSize() {
return new Dimension(mazeSize*10,mazeSize*10);
} //getPreferredSize - this method is used by the scroll pane to adjust its own size automatically
public void drawMaze (Graphics g)
{
/* some irrelevant code that does the desired drawing to the panel by calling g.drawLine()*/
} // drawMaze method that does the de facto drawing
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
drawMaze(g);
}// paintComponent() #Override method - this was the tricky part
}//Drawing JPanel subclass
It is also worth noting (if some noob like myself happens to stumble upon this question), that after instantiating the new JPanel subclass in the action event, I had to add it to the JScrollPanel in the following way, instead of just simply using its add() method:
Drawing drawPanel = new Drawing(textfield1);
scrollPane.getViewport().add(drawPanel);
Again, thanks for the suggestion!
Once finished with the program (a random maze generator that uses a recursive backtracking algorithm), I will make the source code available at my github profile.
We're about to create an online based Space Invaders-game with implemented graphics. I've been reading about JFrames, JPanels and JLabels in order to create a window with a grid where the ships and monsters will be placed in.
So, here's the thing, I've been looking through the different layouts that exists, but nothing really seems to fit our purpose. I would like a simple JFrame with the possibility of placing JLabel-objects on a certain position (with setBounds(), setLocation() or something similar). This requires setLayout(null) which I've heard isn't a good solution? I was thinking of having objects in a fixed 30x30px size, and a fixed window size of 600x600px (giving me a grid of 20*20).
Anyhow, I've been trying to get it to work with setLayout(null), but without any results. If I apply a layout, say FlowLayout, the ship is visible, but stuck in either LEFT, CENTER or MIDDLE.
public class GUI extends JFrame {
JPanel p = new JPanel(null);
public GUI() {
try{
this.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("graphics/bg.png")))));
}catch(IOException e) {
System.out.println("Image does not exist");
}
this.setLayout(null);
this.setResizable(false);
this.setSize(600,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void placeShip1() {
ImageIcon ship2 = new ImageIcon("graphics/ship2.png");
JLabel imageLabel = new JLabel(ship2);
imageLabel.setBounds(200,200,30,30);
p.add(imageLabel);
p.setOpaque(false);
p.setSize(600, 600);
this.add(p);
this.setVisible(true);
}
}
I really can't see why it doesn't work. I mean, all I want is my JFrame with a background image and with an object on a certain position, but instead the object doesn't show at all.
The main reason for wanting to use setLayout(null) is because I was thinking of using a method translating our grid coordinates to the JFrame, simply mapping each coordinate to respective cell.
I am working on a little card game and I have been having some trouble: when I try to add dynamic components to my JLayeredPane it does not display them.
I have a custom component that represents a card and I want to display 2 of them in a layered fashion. For that I have the following class:
public class PairView extends JPanel {
private JLayeredPane layeredPane;
private CardView attackCard;
private CardView defenceCard;
private static Point origin = new Point(0, 0);
private static int offset = 10;
public PairView() {
}
public PairView(Card attackCard) {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(120, 170));
this.defenceCard = null;
this.attackCard = new CardView(attackCard);
this.attackCard.setOpaque(true);
this.attackCard.setForeground(Color.black);
this.attackCard.setBorder(BorderFactory.createLineBorder(Color.black));
this.attackCard.setBounds(origin.x, origin.y, 100, 150);
layeredPane.add(this.attackCard, 0);
this.origin.x += offset;
this.origin.y += offset;
}
public void addDefenceCard(Card defenceCard) throws DurakException {
if (this.defenceCard == null) {
this.defenceCard = new CardView(defenceCard);
this.defenceCard.setOpaque(true);
this.defenceCard.setForeground(Color.black);
this.defenceCard.setBorder(BorderFactory.createLineBorder(Color.black));
this.defenceCard.setBounds(origin.x, origin.y, 100, 150);
layeredPane.add(this.defenceCard, 1);
} else {
throw new DurakException("A defence Card is already present");
}
}
I tested this via the drag and drop interface in NetBeans and I have the following problem:
From what I understand, the default constructor is always called, so when I create 2 random CardView components and add them to the layered pane in the default constructor the parent JFrame display them just fine.
If I use the overwritten constructor or try to add another component (like the addDefenceCard method) it does not display the added component.
calling revalidate() or repaint() isn't doing anything.
How to get the components to show?
Your class extend JPanel, but you never add any components to the panel so there is nothing to display.
You need to add the JLayeredPane to the panel:
layeredPane = new JLayeredPane();
this.add( layeredPane );
I don't know if you need the set the layout to a BoxLayout. The default FlowLayout of the panel will respect the preferredSize of any component added to it.
this.attackCard.setOpaque(true);
this.attackCard.setForeground(Color.black);
this.attackCard.setBorder(BorderFactory.createLineBorder(Color.black));
You may want to consider setting these properties in the constructor of the CardView class. That way the default properties are set in one place and can easily be changed.
Instead of using a layered pane you may want to consider using the Overlap Layout. It was designed to support the requirement of overlapping components.
i found this link.. LINK what i want is there's a JPanel that has a background and another JPanel with half the size of the first JPanel but with an image that is transparent and with a face or a ball at the middle.. :) just like the screenshot from the link.. is that possible to code in java? :) im just thinking it like for web programming. just a sort of DIV's to have that but i dont know in java.. :) sorry for bad english.. :D i have this as a background..
package waterKing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class Main extends JFrame {
MainData data = new MainData();
public static void main(String[] args) {
Main frmMain = new Main();
frmMain.setExtendedState(Frame.MAXIMIZED_BOTH);
frmMain.setVisible(true);
}
public Main() {
data.tk = getToolkit();
data.d = data.tk.getScreenSize();
data.jP = new JPanel() {
protected void paintComponent(Graphics g) {
data.e = getSize();
data.iI = new ImageIcon("images/mainBG.png").getImage();
g.drawImage(data.iI,0, 0, data.d.width, data.d.height, null);
super.paintComponent(g);
}
};
data.jP.setOpaque(false);
data.jSp = new JScrollPane(data.jP);
data.jB = new JButton("EXIT");
data.jB.setBounds(10,10,200,40);
data.jB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
data.jP.setLayout(null);
data.jP.add(data.jB);
this.setTitle("Water King Inventory System");
this.setUndecorated(true);
this.getContentPane();
this.add(data.jSp);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
}
}
i dont know how to add another JPanel to show in the middle with this background
i dont know how to add another JPanel to show in the middle with this background
Its just like adding components to a panel. You need to use a layout manager and then the component will be positioned properly based on the rules of the layout manager. In your case you can set the layout manager of the background panel to be a BorderLayout. Then you can add a JLabel with the appropriate Icon to the center of the BorderLayout.
You will need to set the preferred size (or override the getPreferredSize() method of your panel since you add it to a scroll pane. Scrollbars will only appear when the preferred size of the panel is greater than the size of the scroll pane.
You should not be reading the image in your paintComponent() method since this method is called multiple times.
You should not be using the "screen size" to determine the width/height of the image because the frame will contain a border. You need to use the size of the panel.
Get rid of all the setBounds() code. Learn to use layout managers.
For a general purpose background panel that takes into account most of the suggestions made here check out Background Panel.