The following code, as you see below:
public class app extends javax.swing.JFrame implements Runnable {
extends JFrame. But I also need it to extend JPanel, in order to make a transparent JPanel. The problem is that I can't extend both, java throws a mistake:
If I extend JPanel I'm able to make a transparent JPanel, but the program can't run because there's a mistake in a few lines of code (mistake that disappears if I extend JFrame).
However, if I extend JFrame the program will run just fine, but it keeps me away from doing a transparent JPanel. How can I solve this?
Basically, create your custom class extending from a JPanel, use setOpaque to false to make it transparent.
Create an instance of JFrame, set it to undecorated and adjust it's opacity separately.
Add the custom panel to the frame...
Example
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TransparentPanel {
public static void main(String[] args) {
new TransparentPanel();
}
public TransparentPanel() {
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 TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
try {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/issue459.jpg"));
final JLabel label = new JLabel(new ImageIcon(img.getScaledInstance(-1, 200, Image.SCALE_SMOOTH)));
label.setLayout(new CardLayout());
JPanel menu = new JPanel(new GridBagLayout());
JButton button = new JButton("Show");
menu.add(button);
JPanel transparent = new JPanel(new GridBagLayout());
transparent.setOpaque(false);
transparent.add(new JLabel("Look, I'm see through"));
label.add(menu, "menu");
label.add(transparent, "transparent");
CardLayout layout = (CardLayout) label.getLayout();
layout.show(label, "menu");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout layout = (CardLayout) label.getLayout();
layout.show(label, "transparent");
}
});
add(label);
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
A class can only ever extend one other class, that's why it won't allow you to extend more than 1 class. here is an explanation why that is the case. Perhaps you should try reading this for more information about such window modifications (window transparency and shapes)
If you want specifically a transparent JPanel, perhaps you should look at this answer as it could explain it better than I could.
Related
Can't figure out why this wont work, I get a blank panel added to my gridbag panel.
I added a JLabel("test") between the frames I'm trying to add just to see that something IS getting added, it just isn't visible?
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class Workspace extends JTabbedPane {
static JFrame frame = new JFrame();
private JPanel grid;
private String text = new String("testing.");
Workspace() {
this.addTab("title", growPanel());
}
public static void main(String[] args) throws IOException {
createAndShowGUI();
}
private JPanel growPanel() {
JPanel gp = new JPanel(false);
gp.setPreferredSize(new Dimension(800,600));
//Add a button that adds my frame
JButton addComponentBtn = new JButton("Add Component");
addComponentBtn.addActionListener(e-> {
try {
addComponent();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
gp.add(addComponentBtn, BorderLayout.PAGE_START);
grid = new JPanel(new GridLayout(0, 2, 10, 10)); //any number of rows, 2 columns, H and V gap
JScrollPane sp = new JScrollPane(grid);
sp.setPreferredSize(new Dimension(800,600));
gp.add(sp, BorderLayout.CENTER);
this.setVisible(true);
return gp;
}
void addComponent() throws IOException {
System.out.println("adding");
grid.add(new JLabel("test"));
grid.add(new intf());
this.repaint();
frame.pack();
}
private static void createAndShowGUI() throws IOException {
//Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
frame.add(new Workspace(), BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
And the intf.java class for the JInternalFrame:
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class intf extends JInternalFrame {
public intf () {
super("Document",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
JPanel jp = new JPanel();
JLabel jl = new JLabel("Hi I'm a label");
jp.add(jl);
this.add(jp);
this.pack();
this.repaint();
}
}
Edit:
The JPanel is used to hold the Layout, I don't think I can assign one to the TabbedPane?
Users will load in images which will appear on the left side of the GridLayout (I will upgrade this to a GridBag). After selecting regions on said images, graphs will appear on the right side. This is also why we use a scrollPane so that there is no limit to the number of images loaded. The TabbedPane will be used to split the load if a user loads in too many images (this is all not in the demo code shown here and not relevant to the problem).
The code I posted is for testing why the JInternalFrame doesn't show, so it only shows what is relevant to getting that to work.
Thank you all for your input.
It turned out to be a simple mistake of not having a necessary .setVisible(true)
Under the addComponent() method, the problem is solved when I replace
grid.add(new intf());
with
intf a = new intf();
a.setVisible(true);
grid.add(a);
If I have a JLabel with <u> tag, such as <html><u>text</u>, with WindowsLookAndFeel and WindowsClassicLookAndFeel the underline is not rendered. I have reported this bug.
If no Look and Feel is set, or with Nimbus, all correct.
I know I can set the font attributes of the JLabel, but what if I only want to render one part of the text?
EDIT: I have tested and found that it is a bug of MigLayout combined with UIManger font setting.
Try the code: comment out anyone of UIManager.put("Label.font") or setLayout(MigLayout(xxx)) will solve the problem, but if they are both present, the line is not shown. I changed the title of question to describe it better. Now I see it has nothing to do with L&F, because Nimbus neither render the line.
The effect is:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import net.miginfocom.swing.MigLayout;
public class WindowsLFUnderline extends JDialog {
public WindowsLFUnderline() {
begin();
}
private void begin() {
try {
UIManager.setLookAndFeel(new WindowsClassicLookAndFeel());
//UIManager.setLookAndFeel(new WindowsLookAndFeel());
UIManager.put("Label.font", new Font("SimSun", Font.PLAIN, 13));
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
JTabbedPane tabs = new JTabbedPane();
JLayeredPane layer = new JLayeredPane();
layer.setLayout(new MigLayout("insets 5, fill", "[]", "[]"));
// layer.setLayout(new BorderLayout());
JLabel test = new JLabel("<html><u>TEST</u>");
test.setForeground(Color.BLUE);
test.setBounds(0, 0, 300, 150);
layer.add(test, BorderLayout.CENTER);
tabs.addTab("tab1", layer);
add(tabs, BorderLayout.CENTER);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
WindowsLFUnderline frame = new WindowsLFUnderline();
}
});
}
}
I wanted to create a fairly simple GUI program that switches between panels depending on buttons the user clicked. I searched around and came up with CardLayout being the best suggestion.
Basically in the examples of CardLayout, you create a "card" (a JPanel) and then add each component, like buttons, etc... and switch between the cards.
What I want to create is an object that is a "card" with all the components set up already, in a separate class, and just create an instance of that in the main program. I am a beginner and do not know the best design practices, so I didn't want to create my own class that extended JPanel, which I am pretty sure is terrible design.
You do it just like you would if you had create an instance of JPanel and add the components directly to it.
You need to ensure that the custom class extends from something JComponent or JPanel (preferably) and add them to the container like any other component, for example...
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestCard {
public static void main(String[] args) {
new TestCard();
}
public TestCard() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final CardLayout cardLayout = new CardLayout();
final JPanel cardPane = new JPanel(cardLayout);
cardPane.add(new Card01(), "Card01");
cardPane.add(new Card02(), "Card02");
JToggleButton btnCard01 = new JToggleButton("#1");
JToggleButton btnCard02 = new JToggleButton("#2");
ButtonGroup bg = new ButtonGroup();
bg.add(btnCard01);
bg.add(btnCard02);
JPanel buttons = new JPanel();
buttons.add(btnCard01);
buttons.add(btnCard02);
btnCard01.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardPane, "Card01");
}
});
btnCard02.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardPane, "Card02");
}
});
btnCard01.setSelected(true);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(cardPane);
frame.add(buttons, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Card01 extends JPanel {
public Card01() {
setLayout(new GridBagLayout());
add(new JLabel("#1"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class Card02 extends JPanel {
public Card02() {
setLayout(new GridBagLayout());
add(new JLabel("#2"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
I am making a java application that includes a JWindow. I want to be able to track the mouse without the user having to click the window after going to another window.
Your question is little vague on why you want to continue processing the mouse once it's left the JWindow...but
You have two (basic) choices when it comes to mointoring the mouse outside of your application, you can use a JNI/JNA solution or you can poll MouseInfo.
The following demonstrates the latter, using MouseInfo and a javax.swing.Timer to update a label...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.MouseInfo;
import java.awt.PointerInfo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MouseWindow {
public static void main(String[] args) {
new MouseWindow();
}
public MouseWindow() {
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 JLabel label;
public TestPane() {
setLayout(new BorderLayout());
label = new JLabel();
label.setFont(label.getFont().deriveFont(48f));
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
add(label);
updateMouseInfo();
Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateMouseInfo();
}
});
timer.start();
}
protected void updateMouseInfo() {
PointerInfo pi = MouseInfo.getPointerInfo();
label.setText(pi.getLocation().x + "x" + pi.getLocation().y);
}
}
}
Updated
You may also find Window#setAlwaysOnTop of help to keep the window ontop of the others, if support for the platform
I have created a appointment calendar which essentially is a JPanel which contains other movable and resizable JPanels all surrounded by a JScrollpane, this all works well and I am able to scroll around the JPanel using the scrollbars correctly. I close to finishing my application but would like to achieve one more thing.
What I would like to do is when a user is moving the appointment (JPanel), when you reach the edge of scrollpane it automatically will scroll at a desired speed. I am confused which existing method or class can do this (if there is one) or if anyone knows of a jar library available out there that will suit my needs?
Is that being lazy? Yeah probably, I guess I should code it myself, if you do agree could someone suggest where I would start? I'm still learning Java and I might need a gentle nudge to keep my code clean and tidy.
If I can provide anymore detail to help with an answer, let me know.
Ok, it's actually not much complicated. You need to call setAutoscroll(true); on your "scrollable" component and add a MouseMotionListener which invokes scrollRectToVisible.
Here is a small example code:
import java.awt.BorderLayout;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TestImageResize {
protected void initUI() throws MalformedURLException, IOException {
final JFrame frame = new JFrame(TestImageResize.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage bi = ImageIO.read(new URL(
"http://www.desktopwallpaperhd.net/wallpapers/19/5/islands-paradise-maldive-nature-background-image-landscape-194469.jpg"));
JPanel panel = new JPanel(new BorderLayout());
JLabel label = new JLabel(new ImageIcon(bi));
panel.add(label);
MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
((JPanel) e.getSource()).scrollRectToVisible(r);
}
};
panel.addMouseMotionListener(doScrollRectToVisible);
panel.setAutoscrolls(true);
frame.add(new JScrollPane(panel));
frame.pack();
frame.setSize(frame.getWidth() / 2, frame.getHeight() / 2);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new TestImageResize().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}