How to scale a GUI picture and button location - java

Hello guys it's me again with another question. So I have this program and I basically did what it was supposed to do, but I'm not really implementing the idea of a scroll panel in the program which I should be, because the dimensions for the scroll panel is very large. I only made it large because that's the way I can have my invisible button there without it moving. How can I make my invisible button stay at a particular place of the image instead of layout if you understand what I'm saying? I want the button to stay at a certain point on the image, not on the layout so that If I move the scroll Panel dimensions, it moves with it. sorry If i am bad at explaining things here is my code. Thank you for taking the time to read this.
import java.awt.*;
import javax.swing.*;
public class TransitMap
{
//-----------------------------------------------------------------
// Presents a frame containing a scroll pane used to view a large
// map of the New York transit system.
//-----------------------------------------------------------------
public static void main(String[] args)
{
JFrame frame = new JFrame("New York Transit Map");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setLayout(null);
//frame.setPreferredSize(new Dimension(900, 900));
JPanel mainPane = new JPanel();
mainPane.setLayout(null);
mainPane.setPreferredSize(new Dimension(1300,800));
ImageIcon image = new ImageIcon("fortress.jpg");
JLabel imageLabel = new JLabel(image);
JScrollPane sp = new JScrollPane(imageLabel);
sp.setPreferredSize(new Dimension(400, 400));
sp.setBounds(0, 0, 1300, 800);
JButton button = new JButton("test");
button.setBounds(640,360,50,50);
button.setOpaque(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setToolTipText("<html><img src=\"" +
TransitMap.class.getResource("Bala_Hissar.jpg") +
"\"> <br> This is the fortress ");
mainPane.add(button);
mainPane.add(sp);
frame.getContentPane().add(mainPane);
frame.pack();
frame.setVisible(true);
}
}

Related

How do you make it so that a button doesn't interfere with the location of drawn shape?

So basically when I add a button it essentially pushes the black rectangle drawn in this program down, putting it out of its given location. How would you fix this?
import javax.swing.*;
import java.awt.*;
public class Grid {
public class homeGraphics extends JComponent {
homeGraphics() {
setPreferredSize(new Dimension(450, 600));
}
public void paint(Graphics g) {
super.paint(g);
g.fillRect(200, 275, 50, 50);
}
}
public void homeFrame() {
JFrame frame1 = new JFrame();
frame1.setSize(450, 600);
frame1.setResizable(false);
frame1.setDefaultCloseOperation(frame1.EXIT_ON_CLOSE);
JButton playButton = new JButton("Play");
playButton.setPreferredSize(new Dimension(60, 30));
JPanel panel1 = new JPanel();
panel1.add(playButton);
panel1.add(new homeGraphics());
frame1.add(panel1);
frame1.setVisible(true);
}
public static void main(String args[]) {
Grid frame = new Grid();
frame.homeFrame();
}
}```
it essentially pushes the black rectangle drawn in this program down, putting it out of its given location.
What do you mean out of its location? Painting is always done relative to the component. So your painting will always be done at (200, 275) of the component.
If you are attempting to paint at (200, 275) relative to the "frame", then don't. That is NOT how painting works.
Other problems with your code:
Don't attempt to set the size of your frame. If the custom panel is (450, 600) how can the frame possibly be the same size? The frame also contains the "title bar" and "borders". Instead of using setSize(), you invoke frame.pack()just beforeframe1.setVisible(….)`.
Class names start with an upper case character. Learn by example. Have you ever seen a class name in the JDK that doesn't start with an upper case character?
Custom painting is done by overriding paintComponent(…), not paint().
By default a JPanel uses a FlowLayout. So what you see it the button on one line and then the "HomeGraphics" class is too big to fit on the same line so it wraps the to the second line.
You should be more explicit when you do frame layout. So your code should be something like:
JPanel wrapper = new JPanel();
wrapper.add( playButton );
//JPanel panel1 = new JPanel();
//panel1.add(playButton);
//panel1.add(new homeGraphics());
JPanel panel1 = new JPanel( new BorderLayout() );
panel1.add(wrapper, BorderLayout.PAGE_START);
panel1.add(new HomeGraphics(), BorderLayout.CENTER);
Now the code shows your layout attempt more clearly.

JLabel not showing up on JPanel

For some reason even though I have implemented the validate method in my code, and added my JPanel to my JFrame. I am also trying to get my JLabel to have Comic Sans font and for it to be centered in the screen. Why is my JLabel not showing up on my JPane
package math_program;
import java.awt.Color;
import java.awt.Font;
import java.util.Random;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class Canvas
{
Images obj = new Images();
public void paintFrame()
{
//Instantiation of objects
Random gen = new Random();
JFrame frame = new JFrame();
JPanel panel = new JPanel();
//Text
JLabel problem = new JLabel();
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE); //Make frame actually closeable
frame.setTitle("Math Owl: Alpha V:0.1 (coded by John)");
frame.setSize(800, 500);
frame.setLocationRelativeTo(null);
frame.add(panel); //Add JPanel to JFrame
panel.setVisible(true);
panel.setLayout(null);
panel.setBackground(Color.WHITE); //To see if text is even appearing
//Adding Components
problem.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
problem.setLocation(400,250);
problem.setText(gen.nextInt(11) + " + " + gen.nextInt(11));
panel.add(problem);
panel.validate();
}
}
Use a proper Layout Manager just as copeg said. Even the default Layout Manager (Flow Layout) will work. Just remove panel.setLayout(null); and your JLabel will show up.
Also when I try your snippet code there also problem on Images obj = new Images(); I assume you already have the Images class defined in your package somehow.
`
//frame.add(panel);
frame.setContentPane(panel);
//panel.setVisible(true); // not necessary code
//panel.setLayout(null); // not necessary code
panel.setBackground(Color.WHITE); //To see if text is even appearing
frame.getContentPane().add(problem);
The problem is that with null layout, you have to set both the location and the size of each component. You set only the location of the label, so you can fix it with problem.setSize(x, y);. With that being said, it's just wrong to take this approach. See what your whole GUI design for this frame looks like and choose an appropriate LayoutManager.
Try this:
public class MyCanvas {
public MyCanvas() {
Random gen = new Random();
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel problem = new JLabel();
panel.setBackground(Color.WHITE);
problem.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
problem.setText(gen.nextInt(11) + " + " + gen.nextInt(11));
panel.add(problem); // Default FlowLayout
frame.add(panel); // Default BorderLayout at position CENTER
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Math Owl: Alpha V:0.1 (coded by John)");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new MyCanvas();
}
}
Notes:
frame.setVisible(true) should be the last call you make.
frame.setAlwaysOnTop(true) and frame.setResizable(false) are things you usually want to avoid from the user's perspective.
frame.setSize(...) should be replace with frame.pack().
frame.setLocationRelativeTo(null) should be called between pack() and setVisible(true).
No need for panel.setVisible(true), it does nothing for you.
No need for panel.validate() (should be revalidate()), it is only needed when changing the layout during runtime.
The class Canvas already exists, use a different name.
There two way
is you are using any layout manager then you can simply show the component by using setSize(new Dimension(width, height)
if you have set the layout manager to null then you must use
setBounds(x,y, width, height) (if you do this obviously no need to set size) to show the component
otherwise just do
setSize(new Dimension(width,height)
then setLocation(x,y)
if you want to dynamically calculate the position then you can set the initial locaion as setLocation(0,0)
afterwards when all the components are showing you can use your algorithm to recalculate x and y position and again setLocation(x,y)
for e.g.
label1=setSize(new Dimension(100,20)
label1.setLocation(0,0)
Label2=setSize(new Dimension(100,20)
Label2.setLocation((int)label1.getSize().getWidth()+10,20) and so on

Multiple panels in JFrame

The useless Layout Manager guy is back again, I just can't seem to get my head around these darn layouts and make them work the way I want.
Anyway, I want to have a JFrame which has one large panel at the top (I call it a header) which runs from the left to right side of the frame at the north part of the frame, then four panels below it, two just below the header and two below those, and finally a "footer" panel, basically the same as the header panel, only at the south part of the frame.
Like this:
I had code which had the four middle panels working fine, but the header panel just messed everything up, and I have since been testing with the demo layout manager code for GridBagLayout, GridLayout again and BoxLayout. I can't getting any to work as I want.
For the aware of you here, you will probably notice I've already had a question related to this, and if having two similar questions are not allowed, please make me aware and I will move this to my previous question and this can be closed.
public Shop() {
shopUI = new JFrame("Shop Menu");
shopUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shopUI.setBounds(100, 100, 700, 500);
shopUI.setResizable(false);
allPanels = new JPanel();
headerPanel = new JPanel();
headerPanel.setLayout(new BorderLayout());
headerPanel.setBackground(Color.cyan);
mainPanel = new JPanel();
mainPanel.setLayout(new GridLayout(2,2));
topLeft = new JPanel();
topLeft.setBackground(Color.pink);
topRight = new JPanel();
topRight.setBackground(Color.black);
bottomLeft = new JPanel();
bottomLeft.setBackground(Color.green);
bottomRight = new JPanel();
bottomRight.setBackground(Color.blue);
footerPanel = new JPanel();
footerPanel.setLayout(new BorderLayout());
footerPanel.setBackground(Color.magenta);
mainPanel.add(topLeft);
mainPanel.add(topRight);
mainPanel.add(bottomLeft);
mainPanel.add(bottomRight);
allPanels.add(headerPanel, BorderLayout.NORTH);
allPanels.add(footerPanel, BorderLayout.SOUTH);
allPanels.add(mainPanel);
shopUI.add(allPanels);
shopUI.setVisible(true);
}
I suggest learning about border layout.
for what you want, put the header in the NORTH of the border panel, and the footer in the SOUTH. How you do your other panels depends a bit on what you want them to do; if you always want them to be the same size as each other, you can use a gridlayout for them; if not, you can use boxlayout to lay either the two pairs horizontally or the two pairs vertically, again depending on what you want them to do when the frame resizes.
I think using layout managers is simplified by deciding what you want to happen in the first place, including what happens when the frame is resized. That's a large part of what layouts are all about, anyway -- what stretches, what lines up, etc.
Anyway. what you have there looks like classic BorderLayout to me. Let us know if you need further help. Incidentally, BorderLayout is default for JFrame...
edit...
this will get more interesting when you put something in the panels...
package simpleborderlayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main
{
public static void main(String[] args)
{
Main main = new Main(args);
main.go();
}
public Main(String ... args)
{}
public void go()
{
JPanel headerPanel = getPanel(Color.RED);
JPanel footerPanel = getPanel(Color.BLUE);
JPanel p1 = getPanel(Color.GRAY);
JPanel p2 = getPanel(Color.GRAY);
JPanel p3 = getPanel(Color.GRAY);
JPanel p4 = getPanel(Color.GRAY);
GridLayout gridLayout = new GridLayout(2,2);
JPanel middlePanel = new JPanel(gridLayout);
middlePanel.add(p1);
middlePanel.add(p2);
middlePanel.add(p3);
middlePanel.add(p4);
JFrame mainFrame = new JFrame();
mainFrame.add(headerPanel, BorderLayout.NORTH);
mainFrame.add(middlePanel, BorderLayout.CENTER);
mainFrame.add(footerPanel, BorderLayout.SOUTH);
mainFrame.pack();
mainFrame.setVisible(true);
}
private JPanel getPanel(Color c)
{
JPanel result = new JPanel();
result.setBorder(BorderFactory.createLineBorder(c));
return result;
}
}

JFrame setComponentZOrder() changes size of the objects

I'm trying to write an undecorated JFrame. I'm trying to put my button over my background label. However setting the button's Z order causes the button streches to size of jframe and neither setBounds() nor setSize() changes the situation. Here is my code:
import javax.swing.*;
public class MyApp {
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setBounds(0, 112, 100, 50);
mainFrame.setLayout(null);
mainFrame.setUndecorated(true);
JLabel lblBackground = new JLabel(new ImageIcon(JFrame.class.getResource("/res/green.png")));
lblBackground.setBounds(0, 0, 100, 50);
JButton btnStart = new JButton("");
btnStart.setBounds(5, 15, 10, 15);
mainFrame.add(lblBackground);
mainFrame.add(btnStart);
mainFrame.setComponentZOrder(btnStart, 0);
mainFrame.setComponentZOrder(btnStart, 1);
mainFrame.setVisible(true);
}
}
Thanks for replies.
Use a JLayeredPane for this.
You will need to create a new JLayeredPane:
JLayeredPane layered = new JLayeredPane();
Set your JFrame to use this as a content pane:
mainFrame.setContentPane(layered);
And add your components, in this format:
layered.add(Component c, int layerNumber);
Hope that works for you!
More on JLayeredPanes
Don't play with null layouts. Swing was designed to be used with layout managers
Add the button to the label. For example:
JLabel label = new JLabel(...);
label.setLayout( new FlowLayout() );
JButton button = new JButton(...);
label.add( button );
frame.add(label);
frame.pack();
frame.setVisible(true);
Now the frame should be the same size as your image. The button should be centered on the top of the image. If you want the button positioned somewhere else then use a different layout manager.

Swing: Showing a transparent Panel hovering over another Panel

I want to show a textArea showing some text (will show log lines) , and have an animated gif hoovering above it. I tried the solution described here , but all I get is a grey screen. Hints?
public class TestLayeredPanes {
private JFrame frame = new JFrame();
private JLayeredPane lpane = new JLayeredPane();
public TestLayeredPanes() {
frame.setPreferredSize(new Dimension(600, 400));
frame.setLayout(new BorderLayout());
frame.add(lpane, BorderLayout.CENTER);
//Build the animated icon
JLabel buildingIcon = new JLabel();
buildingIcon.setIcon(new ImageIcon(this.getClass().getResource(
"/com/ct/tasks/cmviewer/gui/progress_bar.gif")));
JPanel iconPanel = new JPanel();
iconPanel.add(buildingIcon);
//Build the textArea
JTextArea textLog = new JTextArea("Say something");
JPanel textPanel = new JPanel();
textPanel.add(new JScrollPane(textLog));
//Add the panels to the layered pane
lpane.add(textPanel, 0);
lpane.add(iconPanel, 1);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new TestLayeredPanes();
}
}
Try putting your animated GIF on the glass pane of your root pane:
http://download.oracle.com/javase/tutorial/uiswing/components/rootpane.html
JXLayer make easier to do that. Look at JXLayer samples.
You also can take a look at code of XSwingX
Since you started with a working example, why did you remove lines of code from the example you copied?
Layered panes don't use a layout manager therefore the size of your components are (0, 0), so there is nothing to display. The setBounds(...) method in the example are there for a reason.

Categories