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
Related
I'm new in java swing programming. What i'm trying to do is paint a string to a specific location in a JPanel. The JPanel is very large and so i add it to a JScrollpane, but when i draw the string it is printed not just in the specified location but also in others.
The first image represents the bottom of the panel where i decided to draw the string and this is correct. But if you observe whole the panel you can find the string too in others locations (see second image).
Can someone tell me why this happen? How can i prevent it?
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
class Example extends JFrame
{
private MyPanel gg=new MyPanel();
Example(){
add(new JScrollPane(gg));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(MAXIMIZED_BOTH);
}
public static void main(String argv[]){
EventQueue.invokeLater(new Runnable() {
public void run() {
Example test=new Example();
test.setVisible(true);
}
});
return;
}
}
class MyPanel extends JPanel
{
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
g2d.drawString("HI I LOVE ELON MUSK", 90, 300035);
return;
}
public Dimension getPreferredSize() {
return new Dimension(500, 300060);
}
}
Your code ran fine on my Windows 10 system. I have a Java 13 JDK that I compile at Java 8.
I made a few changes to your main class. Maybe these changes stabilized the display. Run my code on your system and see.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class LongJPanelExample {
public LongJPanelExample() {
JFrame frame = new JFrame("Long JPanel Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel gg = new MyPanel();
frame.add(new JScrollPane(gg));
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String argv[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new LongJPanelExample();
}
});
}
}
class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("HI I LOVE ELON MUSK", 90, 300035);
return;
}
public Dimension getPreferredSize() {
return new Dimension(500, 300060);
}
}
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?
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.
ok so i am trying to make a small java paint program but i am having trouble trying to get my buttons to work. I was able to get one color when i instantiated the MyPanel class, but i changed it around in an attempt to make use of my buttons. I basically have it setup to where each button activates a certain constructor in the MyPanel class and each constructor activates the appropriate methods to change the colors so I can draw. Im really new to programming so any advice you guys could give me would be much appreciated. I also have an extra class that is instantiated in the MyPanel class which i didnt bother putting in because i know the problem isnt in there. All the Red class does is set the color
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
public class Driver
{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
SwingUtilities.isEventDispatchThread();
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton red = new JButton("red");
JButton blue = new JButton("blue");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
frame.pack();
frame.setSize(1000,1000);
panel.add(red);
panel.add(blue);
blue.addActionListener( new Action() );
red.addActionListener( new Action() );
}
}//end driver class
public class Action implements ActionListener
{
public void actionPerformed( ActionEvent e )
{
MyPanel d = new MyPanel();
}
}//end Action
public class MyPanel extends JPanel
{
private int xCoord = 50;
private int yCoord = 50;
private int squareW = 20;
private int squareH = 20;
Red red = new Red();
public MyPanel()
{
setBorder(BorderFactory.createLineBorder(Color.yellow));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquarer(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquarer(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y)
{
if ((xCoord != x) || (yCoord!= y)) {
repaint(xCoord,yCoord,squareW+1,squareH+1);
red.setX(x);
red.setY(y);
repaint(red.getX(),red.getY(),red.getWidth()+1,red.getLength()+1);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("hi",10,20);
red.paintSquare(g);
} //end MyPanel
I basically have it setup to where each button activates a certain
constructor in the MyPanel class and each constructor activates the
appropriate methods to change the colors so I can draw.
I can't see it since your ActionListener is the same for both buttons:
private static void createAndShowGUI() {
...
blue.addActionListener( new Action() );
red.addActionListener( new Action() );
...
}
public class Action implements ActionListener {
#Override
public void actionPerformed( ActionEvent e ) {
MyPanel d = new MyPanel();
}
}
This method doesn't even add this new panel to the frame so it will never be visible.
Also what is this object?
Red red = new Red();
Suggested approach
You may follow this suggested tips to achieve your goal:
Provide MyClass with a method to set the desired color.
Add an instance of this panel (or many as needed) to the frame when you initialize your GUI. Note: this/these may be added dinamically but you need to follow the hints about adding components to a displayed container described here
Use action listener to set the panel color as you whish.
For instance:
public class MyPanel extends JPanel {
private Color color = Color.red;
// this color should be used within paintComponent() method
public void setColor(Color newColor) {
color = newColor;
repaint();
}
...
}
When adding a JPanel that has graphics to a JFrame, it's working fine. But when I try to add a JPanel in which I have added another JPanel with graphics, its not showing in the JFrame. Please see code below
package sample;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JFrame{
public static void main(String[] args) {
new Main();
}
public Main(){
setTitle("Sample");
setVisible(true);
setSize(500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(new SamplePanel2());
}
}
class SamplePanel2 extends JPanel{
public SamplePanel2(){
add(new JButton("Hi"));
add(new SamplePanel());
}
}
class SamplePanel extends JPanel {
public SamplePanel(){
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("HHHHHHHHHHHH", 100, 100);
}
}
Please do watch the constructor of the Main Class, make this your habbit to follow the sequence as shown in this example. First add components to the JFrame then only make calls like pack(), setSize() or setVisible(...), not before that.
Always make it your habbit, that whenever you override paintcomponent() method, override getPreferredSize() method as well.
And always put calls like pack()/setVisible(...) inside the EDT - Event Dispatch Thread. Please read Concurrency in Swing, for more detail on the topic.
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JFrame{
public static void main(String[] args) {
new Main();
}
public Main(){
setTitle("Sample");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setContentPane(new SamplePanel2());
pack();
setVisible(true);
}
}
class SamplePanel2 extends JPanel{
public SamplePanel2(){
add(new JButton("Hi"));
add(new SamplePanel());
}
}
class SamplePanel extends JPanel {
public SamplePanel(){
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(300, 300));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("HHHHHHHHHHHH", 100, 100);
}
}