JFrame - Manual Resizing Issue - java

Good evening,
I created a window with a costum layout and a JPanel. When I resize it manually, it flickers because Java draws the JPanel false to draw it a second time at the right position.
I made a short example-program including my problem:
public class Starter {
private static TestWindow testWindow;
public static void main(String[] args) {
testWindow = new TestWindow();
}
}
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestWindow {
private JFrame frame;
public TestWindow() {
frame = new JFrame();
frame.setBounds(100, 100, 765, 599);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setLayout(new OwnLayout());
JPanel pnl = new JPanel();
pnl.setBackground(Color.BLUE);
frame.add("", pnl);
}
}
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import javax.swing.JPanel;
public class OwnLayout implements LayoutManager {
JPanel pnl;
public OwnLayout() {
}
#Override
public void addLayoutComponent(String name, Component comp) {
pnl = (JPanel) comp;
}
#Override
public void layoutContainer(Container parent) {
if (pnl != null)
pnl.setBounds((int) parent.getWidth() - 50, 0, 50, (int) parent.getHeight());
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
#Override
public Dimension preferredLayoutSize(Container parent) {
return null;
}
#Override
public void removeLayoutComponent(Component comp) {
pnl = null;
}
}
The flickering only appears, when dragging the left border of the frame.
The issue may link to:
Due to the asynchronous nature of native event handling, the results
returned by getBounds, getLocation, getLocationOnScreen, and getSize
might not reflect the actual geometry of the Window on screen until
the last request has been processed. During the processing of
subsequent requests these values might change accordingly while the
window management system fulfills the requests.
(quoted from https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html)
I need a solution to prevent the flickering. Does anyone have an idea?

Related

Why is JPanel still painted?

I am actually trying to create a JPanel, containing a bunch of ui elements for the user to manipulate the application. This panel is placed on top of Java3D scene. Therefore, I wanted the background of this JPanel to be transparent. Neither panel.setBackground(new Color(0,0,0,0)) nor popupPanel.setOpaque(false) nor both calls made the panel background transparent. So I decided to sub-class JPanel and play with paintComponent. No effect. Then I tried paint. Nothing. Then I got confused. So I overwrote literally every method I know of, related to painting a JPanel and left each method body blanc (see below). When I run the application, I still get the panel. How can that be? I placed some System.out.println to be sure that the class is the right one, and is called. It is the right one. Despite all this missing code, the only difference to a normal JPanel is that the button is only painted if the mouse enters the button bounds. What am I missing?
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class TransparentPanel extends JPanel {
protected Color bg = new Color(0,0,0,0);
public TransparentPanel() {
super();
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) { }
#Override
public void paint(Graphics g) {
System.out.println(System.getProperty("java.vendor"));
System.out.println(System.getProperty("java.version"));
for(Component c: getComponents()) {
System.out.println(c.toString());
}
}
#Override
public void repaint(Rectangle r) {}
#Override
public void repaint(long tm,int x,int y,int width, int height) {}
#Override
protected void paintChildren(Graphics g) {}
#Override
protected void paintBorder(Graphics g) {}
#Override
public void paintImmediately(int x,int y,int width, int height) {}
#Override
public void paintImmediately(Rectangle r) {}
}
and
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
public class OverlayoutTest extends JFrame {
public OverlayoutTest() {
super("Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(new Dimension(400, 300));
add(createPanel());
setLocationRelativeTo(null);
setVisible(true);
}
private JPanel createPanel() {
JPanel mainPanel = new JPanel(){
#Override
public boolean isOptimizedDrawingEnabled() {
return false;
}
};
mainPanel.setLayout(new OverlayLayout(mainPanel));
JComponent popupPanel = createPopupPanel();
popupPanel.setAlignmentX(1.0f);
popupPanel.setAlignmentY(0.0f);
mainPanel.add(popupPanel);
SpatialView view = new SpatialView(null); // A class extending JPanel containing a Java3D Canvas3D in a BorderLayout
mainPanel.add(view);
view.addScaledPlanetModel();
return mainPanel;
}
private JComponent createPopupPanel() {
TransparentPanel popupPanel = new TransparentPanel();
// popupPanel.setBackground(new Color(0,0,0,0));
// popupPanel.setOpaque(false);
popupPanel.setMaximumSize(new Dimension(250, 300));
JButton button = new JButton("HI there!"); // the button does nothing but is nice to spot
button.setForeground(Color.WHITE);
popupPanel.add(button );
return popupPanel;
}
public static void main(String[] args) {
new OverlayoutTest();
}
}
I am using OpenJDK version "11" 2018-09-25, build 11+28 and Java3D 1.7.0

Java Graphics Only Paint on Button Click

I'm not sure how java graphics work. It seems
to be executing something itself so I am trying to break it
down.
I'm trying to create the blank JPanel and then only draw to it
once the JButton has been clicked but it doesn't work
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class testGui {
// global ======================================================================
static gui gc_gui;
// main ========================================================================
public static void main(String[] args) {
gc_gui = new gui();
gc_gui.cv_frame.setVisible(true);
listeners();
}
// action listeners ============================================================
public static void listeners() {
ActionListener ll_square = new ActionListener() {
public void actionPerformed(ActionEvent event) {
gc_gui.cv_content.draw(graphic);
}
};
gc_gui.cv_button.addActionListener(ll_square);
}
// gui =========================================================================
public static class gui {
JFrame cv_frame;
JButton cv_button;
content 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_button = new JButton("Square");
cv_content = new content();
cv_content.setBackground(Color.BLACK);
cv_content.setPreferredSize(new Dimension(500, 300));
cv_frame.add(cv_button);
cv_frame.add(cv_content);
}
}
// content =====================================================================
public static class content extends JPanel {
public void paint(Graphics graphic) {
super.paint(graphic);
}
public void update() {
super.repaint();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.setPaint(Color.RED);
graphic2D.fillRect(10, 10, 100, 100);
}
}
}
I create the content JPanel without the draw function being
called and then I try to call it using my ActionListener
although it is crashing because of the graphic variable.
What is the correct way to use the java graphics utility?
UPDATE
Maybe I'm not asking this question right but it is possible to
create a blank image.
Then draw additional images to that images (squares) after a button
has been clicked?
not just updating the dimensions using global variables but generating
new images to that existing image
but it is possible to create a blank image. Then draw additional images to that images (squares) after a button has been clicked?
Check out Custom Painting Approaches for two common ways to do painting.
The example allows you to draws Rectangles with the mouse. In your case the logic will be simpler as you would just invoke the addRectangle(...) method when you click a button. Of course you need to set the size/location of the Rectangle somehow.
import java.awt.Color;
import java.awt.Graphics;
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.border.LineBorder;
public class TestGui {
public static Content content;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Test GUI");
frame.setSize(429, 385);
frame.getContentPane().setLayout(null);
JButton cv_button = new JButton("Square");
cv_button.setBounds(10, 159, 70, 23);
frame.getContentPane().add(cv_button);
cv_button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Content.isToDraw = true;
content.paintImmediately(content.getBounds());
Content.isToDraw = false;
}
});
JButton cv_buttonClear = new JButton("Clear");
cv_buttonClear.setBounds(10, 179, 70, 23);
frame.getContentPane().add(cv_buttonClear);
cv_buttonClear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
content.paintImmediately(content.getBounds());
}
});
content = new Content();
content.setBorder(new LineBorder(new Color(0, 0, 0)));
content.setBounds(87, 11, 287, 312);
frame.getContentPane().add(content);
frame.setVisible(true);
}
}
class Content extends JPanel {
public static Boolean isToDraw = false;
public void paintComponent(Graphics arg0) {
if (isToDraw) {
arg0.setColor(Color.RED);
arg0.fillRect(0, 0, getWidth(), getHeight());
} else {
super.paintComponent(arg0);
}
}
}

How to remove JInternalFrame's Border?

I've searched about removing JInternalFrame's border, n I've got answer here. But now my query is after applying border to null, the border is not removed. As per second answer given in the question, I've tried to set border to Empty border n I've got success. And finally, my questions are as below.
Why border is not removed even if I set border to null (e.g. jif.setBorder(null);)?
I've set border to empty border (e.g. jif.setBorder(BorderFactory.createEmptyBorder());), but the titlebar of JInternalFrame is still visible, how to hide JInternalFrame's Title with its border?
Edited by Girish
My Code sample is as below:
package com.laxmiagencies.ui;
import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MDIParent extends JFrame {
private static final long serialVersionUID = -7911142498378226657L;
public JDesktopPane jdp;
private JLabel apptitle;
private MDIListener listen;
public JMenuBar menubar;
private boolean islogin;
private boolean enablelogin;
private JMenuItem mnuabout;
public MDIParent()
{
super();
enablelogin=false;
init();
}
public MDIParent(String apptitle)
{
super(apptitle);
enablelogin=false;
init();
}
public MDIParent(String apptitle, boolean enablelogin)
{
super(apptitle);
this.enablelogin=enablelogin;
init();
}
public MDIParent(boolean enablelogin)
{
super();
this.enablelogin=enablelogin;
init();
}
public boolean isLoginEnabled()
{
return enablelogin;
}
public void setLoginEnabled(boolean enablelogin)
{
this.enablelogin=enablelogin;
this.islogin=!this.enablelogin;
}
public boolean isLoggedIn()
{
return islogin;
}
private void init()
{
listen=new MDIListener();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
jdp=new JDesktopPane();
jdp.setBounds(0, 0, getWidth(), getHeight());
jdp.addContainerListener(listen);
add(jdp);
setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height-50);
apptitle=new JLabel(getTitle());
apptitle.setBounds(20, 50, getWidth()-30, 70);
jdp.add(apptitle);
menubar=new JMenuBar();
mnuabout=new JMenuItem("About Us");
mnuabout.addActionListener(listen);
menubar.add(mnuabout);
setJMenuBar(menubar);
islogin=!enablelogin;
addComponentListener(listen);
}
public void setAppTitle(String apptitle)
{
setTitle(apptitle);
this.apptitle.setText(apptitle);
}
public void setTitleFont(Font font)
{
apptitle.setFont(font);
}
public void setTitleForeColor(Color color)
{
apptitle.setForeground(color);
}
//INFO Listener Class
private class MDIListener implements ComponentListener, ActionListener, ContainerListener
{
//INFO Used Methods
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==mnuabout)
{
AboutUs abt=new AboutUs();
jdp.add(abt);
abt.setVisible(true);
}
}
#Override
public void componentResized(ComponentEvent e)
{
jdp.setBounds(0, 0, getWidth(), getHeight());
for(JInternalFrame frame:jdp.getAllFrames())
{
frame.setSize(jdp.getWidth()-15, jdp.getHeight()-60);
}
}
#Override
public void componentShown(ComponentEvent e)
{
if(enablelogin)
{
if(!islogin)
{
setEnabled(false);
LoginWindow login=new LoginWindow();
login.setUndecorated(true);
login.setAlwaysOnTop(true);
login.setVisible(true);
}
}
}
#Override
public void componentAdded(ContainerEvent e)
{
if(e.getChild() instanceof JInternalFrame)
{
JInternalFrame child=(JInternalFrame)e.getChild();
child.setBounds(0, 0, jdp.getWidth()-15, jdp.getHeight()-60);
child.setBorder(javax.swing.BorderFactory.createEmptyBorder());
}
}
//INFO Unused methods
#Override
public void componentRemoved(ContainerEvent e){}
#Override
public void componentHidden(ComponentEvent e){}
#Override
public void componentMoved(ComponentEvent e){}
}
}
The JInternalFrame code is as follows
import javax.swing.BorderFactory;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
public class AboutUs extends JInternalFrame {
/**
*
*/
private static final long serialVersionUID = -4542063025572303166L;
private JPanel panel;
public AboutUs()
{
setTitle("About Us");
setLayout(null);
panel=new JPanel();
panel.setSize(200, 200);
panel.setBorder(BorderFactory.createTitledBorder("About Us"));
add(panel);
setMaximizable(true);
}
public JPanel getPanel()
{
return panel;
}
}
I've another question one:
3. How to disable of dragging JInternalFrame? i.e. the JInternalFrame must not be moved by user.
How to remove JInternalFrame's Border?
You use:
internalFrame.setBorder( null );
This works for me using JDK8 in Windows 7. If it doesn't work for you post a proper SSCCE.
how to hide JInternalFrame's Title with its border?
You can use the following. It will still leave a little border at the top if the internal frame to allow you to drag the frame around
internalFrame.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);
If you don't need the dragging functionality then real question is why are you trying to remove the border? The point if using an internal frame is to allow the user to freely move the frame around the desktop by dragging the frame.
If all you need is a panel without a Border, then use a JPanel and add the panel to a parent panel. There is no need for the complexity of a JDestopPane/JInternalPane if you are not going to use those features.

Java GUI: Image will be overwritten, Path the same -> show it in the frame (image still the same)

I want to show a changing image on my frame. The imagepath is always the same, but the image will be getting overwritten every 10 seconds from another program.
The problem is that the image is not changing when I overwrite it with another image with the same name. So in my understanding: Compiler looks every look in the path and gets the image -> when the image changed it will be changed on the frame!
I hope you understand my problem and somebody could help me.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GUI extends JFrame{
public ImageIcon imageBar;
public JLabel labelimage1;
private JLabel labelimage2;
private JLabel bar1 = new JLabel();
private JLabel bar2 = new JLabel();
private JLabel bar3 = new JLabel();
private JLabel bar4 = new JLabel();
private JLabel bar5 = new JLabel();
private JButton buttonBar1 = new JButton("1");
private JButton buttonBar2 = new JButton("2");
private JButton buttonBar3 = new JButton("3");
private JButton buttonBar4 = new JButton("4");
private JButton buttonBar5 = new JButton("5");
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel();
private JPanel panel3 = new JPanel();
private JFrame window = new JFrame("Interface");
public GUI(){
//set the layouts
panel1.setLayout(new GridLayout(1, 2));
panel2.setLayout(new GridLayout(2, 1));
panel3.setLayout(new GridLayout(2, 5));
//place Panel2 and Panel3 in the window
panel1.add(panel2);
panel1.add(panel3);
//----Panel2
//refreshImage();
//----Panel3
panel3.add(buttonBar1); //add the bars 1-5 on panel3
panel3.add(buttonBar2);
panel3.add(buttonBar3);
panel3.add(buttonBar4);
panel3.add(buttonBar5);
//configure the frame
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setSize(800, 400);
window.getContentPane().add(panel1);
}
public void refreshImage() {
panel2.removeAll(); //delete the old panel
//panel2.repaint();
//panel2.revalidate()
DrawImage pan = new DrawImage();
panel2.add(pan);
panel2.add(labelimage2);
}
}
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class DrawImage extends JPanel implements ActionListener{
private ImageIcon image;
public DrawImage(){
image = new ImageIcon("C:\\Users\\usuario\\Desktop\\image.png");
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
image.paintIcon(this, g, 50, 50);
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
import java.io.File;
public class Main {
public static void main(String[] args) {
GUI Interface = new GUI();
while(true)
{
Interface.refreshImage();
try {
Thread.sleep(5000); //wait for 5000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thank you very much!
The likely cause is Java is caching the image in memory, associated with the source name. So rather then trying to reload the image again, Java simply returns the cached version.
You could use ImageIcon#getImage#flush to force Java to reconstruct the image
Problems
You are calling refreshImage from a Thread other then the Event Dispatching Thread, this could cause issues with the updating of the components and cause rendering artifacts
You are forcefully removing the DrawImage pane and adding a new instance, rather the trying to reload the image
You're calling repaint within the paintComponent method, don't do this...
You should consider using a Swing Timer, which will allow you to schedule a regular update and be notified within the context of the Event Dispatching Thread.
You could provide a simple refresh method which flushes the current ImageIcon and schedule a repaint of the panel...or you could just use a JLabel and save your self the time
An example of Image#flush
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SlideShow {
public ImageIcon imageBar;
public static void main(String[] args) {
new SlideShow();
}
public SlideShow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawImage());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawImage extends JPanel {
private ImageIcon image;
public DrawImage() {
image = new ImageIcon("D:\\thumbs\\image.png");
Timer timer = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
refresh();
}
});
timer.start();
}
public void refresh() {
image.getImage().flush();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image.getImage(), 0, 0, this);
}
}
}
The problem with this, is because the image data is loaded in a background thread, it won't may no be available when the component is first repainted, which could make the component appear to flicker.
A better approach would be to use ImageIO.read, which will ensure that the image is fully loaded before the method returns, the draw back here is that could cause the application to "pause" momentary as the image is loaded, personally, I'd use the refresh method to stop the the Timer (or set the Timer to non-repeating), start a background Thread to load the image (using ImageIO.read) call repaint (which is thread safe) and restart the Timer...
Your while (true) loop risks typing up the Swing event thread locking your program. If it doesn't do that, then you risk unpredictable threading issues by making Swing calls off of the event Thread. These problems can be solved easily by your using a Swing Timer not a while true loop to do your swapping.
Rather than removing and adding components, why not simply display images as ImageIcons within a single non-swapped JLabel.
To swap images here, simply call setIcon(...) on the JLabel.
For an example of using a Swing Timer to swap images, please check out my answer to a similar question here.
For example:
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TimerImageSwapper {
public static final String[] IMAGE_URLS = {
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_01.png",
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_02.png",
"http://imaging.nikon.com/lineup/dslr/d7000/img/sample/img_04.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_08.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_05.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_01.png",
"http://imaging.nikon.com/lineup/dslr/d3200/img/sample/img_06.png" };
private ImageIcon[] icons = new ImageIcon[IMAGE_URLS.length];
private JLabel mainLabel = new JLabel();
private int iconIndex = 0;;
public TimerImageSwapper(int timerDelay) throws IOException {
for (int i = 0; i < icons.length; i++) {
URL imgUrl = new URL(IMAGE_URLS[i]);
BufferedImage image = ImageIO.read(imgUrl);
icons[i] = new ImageIcon(image);
}
mainLabel.setIcon(icons[iconIndex]);
new Timer(timerDelay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
iconIndex++;
iconIndex %= IMAGE_URLS.length;
mainLabel.setIcon(icons[iconIndex]);
}
}).start();
}
public Component getMainComponent() {
return mainLabel;
}
private static void createAndShowGui() {
TimerImageSwapper timerImageSwapper;
try {
timerImageSwapper = new TimerImageSwapper(5 * 1000);
JFrame frame = new JFrame("Timer Image Swapper");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(timerImageSwapper.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

I'm trying to draw a filled rectangle over an imageIcon using the coordinates of the image and the rectangle appears off

Eventually after I work out this small detail it will receive a building and room number to outline said building and room number so it is easy to locate but I can't get the rectangle to draw even close to acurately over a single room.
package programSTLApp;
/*
Program to request the classroom no. in STLCC and Display the location of
that classroom.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class STLApp extends JFrame
{
private JLabel imageLabel;
private JButton button;
private JPanel imagePanel;
private JPanel buttonPanel;
public STLApp()
{
super("My STLCC Class Locator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
buildImagePanel();
buildButtonPanel();
add(imagePanel, BorderLayout.CENTER);
add(buttonPanel,BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void buildImagePanel()
{
imagePanel = new JPanel();
imageLabel = new JLabel("Click the button to see the drawing indicating "
+ "the location of your class");
imagePanel.add(imageLabel);
}
private void buildButtonPanel()
{
buttonPanel = new JPanel();
button = new JButton("Get Image");
button.addActionListener(new ButtonListener());
buttonPanel.add(button);
}
private class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
ImageIcon SiteLayoutFV = new ImageIcon("D:\\B120.jpg");
imageLabel.setIcon(SiteLayoutFV);
imageLabel.setText(null);
pack();
}
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.RED);
g.fillRect(55,740,164,815);
}
public static void main(String[] args)
{
new STLApp();
}
}
As has already being pointed out, top level containers ain't a studiable class for performing custom painting, there is just to much going with these containers to make it easy to paint to.
Instead, create yourself a custom component, extending from something like JPanel, and override it's paintComponent method.
Once you have the floor pane rendered, you can render you custom elements over the top of it.
How you store this information is up to you, but basically, you need some kind of mapping that would allow you to take the floor/room and get the Shape that should be rendered.
Because the floor map might float (it may not always be rendered at 0x0 for example), you need to be able to translate the coordinates so that the Shape will always match.
Take a look at...
Performing Custom Painting
2D Graphics
For more details
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class FloorPlan {
public static void main(String[] args) {
new FloorPlan();
}
public FloorPlan() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage floorPlan;
private Rectangle myOffice = new Rectangle(150, 50, 32, 27);
public TestPane() {
try {
floorPlan = ImageIO.read(new File("floorPlan.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return floorPlan == null ? new Dimension(200, 200) : new Dimension(floorPlan.getWidth(), floorPlan.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (floorPlan != null) {
int x = (getWidth() - floorPlan.getWidth()) / 2;
int y = (getHeight() - floorPlan.getHeight()) / 2;
g2d.drawImage(floorPlan, x, y, this);
g2d.setColor(Color.RED);
g2d.translate(x, y);
g2d.draw(myOffice);
}
g2d.dispose();
}
}
}

Categories

Resources