Text in transparent windows ( AWTUtilities.setWindowOpaque(window, false) ) is not antialiased correctly, and looks different then in opaque windows.
I'm using JDK 7.40.
Any idea how to workaround it?
In the program below the button text is not antialiased (correctly). Removing the setWindowOpaque() fixes the antialiasing.
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import com.sun.awt.AWTUtilities;
public class TransparentFrame extends JFrame
{
public TransparentFrame()
{
setUndecorated(true);
AWTUtilities.setWindowOpaque(this, false);
add(new JButton(new ExitAction()));
}
public static void main(String[] args)
{
JFrame frame = new TransparentFrame();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class ExitAction extends AbstractAction
{
public ExitAction()
{
super("Exit");
}
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
}
Related
I'm trying to make a a program in MVC architecture which simply opens a frame (JFrame) with some certain design and when clicked somewhere with a mouse simply prints to the console : "sth" notifying that the action went through successfully but it seems that the Input.java class when added to the frame before the Ouput.java class is overridden by the latter and disables MouseListener, or the former overrides the latter where you're able to activate MouseListener executing a certain program when clicked on the frame but doesn't show the design made in Output
Here are the mentioned class files:
input.java:
package MouseListenerTest;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
public class Input extends JPanel implements MouseListener
{
Input()
{
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
System.out.println("Ej Adiiiii");
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
Output.java
package MouseListenerTest;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Output extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
}
Frame.java
package MouseListenerTest;
import javax.swing.*;
public class Frame
{
Frame()
{
JFrame frame = new JFrame();
frame.getContentPane().add(new Output());
frame.getContentPane().add(new Input());
frame.setSize(500,500);
frame.setVisible(true);
frame.setTitle("MouseListener test");
}
}
Controller.java
package MouseListenerTest;
public class Controller
{
public static void main(String[] args)
{
new Frame();
}
}
How do I fix this problem?
the problem in your code is because the way you added the elements to frame and I changed to a GridLayout and added them to frame to see both:
frame.setLayout(new GridLayout(2, 1));
frame.getContentPane().add(new Output());
frame.getContentPane().add(new Input());
more info about Layout Manager
You will have to learn at least the basics about laying out components.
Basically, I want to get the coordinates of the mouse when it is pressed. I've done it before and I know it's possible, but it doesn't seem to be working with my current jframe/jpanel set up and I cannot understand why.
Here's a summary of my mouselistener code:
package com.JJEngine.input;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import com.JJEngine.output.Window;
public class Mouse implements MouseListener {
public Mouse(){
}
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
//This is where i'd do my stuff if this actually worked
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
and here's my jpanel/jframe
package com.JJEngine.output;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.JJEngine.input.Mouse;
import com.JJEngine.main.Main;
import custom.GameMain;
public class Window extends JPanel{
public static JFrame frame = new JFrame();
public static JPanel gamePanel = new JPanel();
private Container window;
public Window() {
frame.addMouseListener(new Mouse());
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(!GameMain.BORDERS);
frame.setVisible(true);
// Custom options
frame.setSize(Main.game.X, Main.game.Y);
frame.setTitle(Main.game.NAME);
frame.setResizable(Main.game.RESIZABLE);
window = frame.getContentPane();
frame.add(gamePanel);
frame.add(Main.render);
// Built options
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setFocusable(true);
frame.setAlwaysOnTop(true);
}
}
My guess is I will have to restructure my entire Window class. If that is the case, why? Thanks in advance.
How to Disable/Enable JFrame components when JInternalFrame isVisible inside JFrame/JDesktopPane? For example, make every JInternalFrame1 visible on the JDesktopPane (desktop pane set on the JFrame) all frame components like JMenuBar/JButton/etc. set disabled.
Have a solution?
If you have a reference to all your components, the best shot is to write a simple method that would disable everything (more or less like a state machine).
If you don't have a reference to all of them (like a GUI that uses reflection) you will need to get a root panel and iterate over it finding every component and disabling it.
Take a look at the Jemmy tool that is used to test Netbeans, they have a GUIBrowser that can give you an idea.
That makes use of JXLayer and JHLabs filters, basically, it creates a custom frame that wraps the JRootPane in a JXLayer, which allows you to "disable" the entire frame...
import com.jhlabs.image.BlurFilter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.effect.BufferedImageOpEffect;
import org.jdesktop.jxlayer.plaf.ext.LockableUI;
public class EnabledFrame {
public static void main(String[] args) {
new EnabledFrame();
}
public EnabledFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final LayeredFrame frame = new LayeredFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
JMenuBar mb = new JMenuBar();
JMenu mFile = new JMenu("File");
mFile.add("Exit");
frame.setJMenuBar(mb);
mb.add(mFile);
JButton btn = new JButton("Click me");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setEnabled(false);
}
});
frame.add(btn);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LayeredFrame extends JFrame {
private BlurableLockedUI lockUI;
private JXLayer<JRootPane> rootLayer;
public LayeredFrame(String title) throws HeadlessException {
super(title);
}
#Override
protected void setRootPane(JRootPane root) {
if (rootLayer != null) {
remove(rootLayer);
}
super.setRootPane(root);
JRootPane rootPane = getRootPane();
rootLayer = new JXLayer<>(root);
rootLayer.setUI(getLockUI());
add(rootLayer, BorderLayout.CENTER);
}
protected BlurableLockedUI getLockUI() {
if (lockUI == null) {
lockUI = new BlurableLockedUI();
}
return lockUI;
}
#Override
public void setEnabled(boolean b) {
getLockUI().setLocked(!b);
super.setEnabled(b);
}
}
public class BlurableLockedUI extends LockableUI {
public BlurableLockedUI() {
super(new BufferedImageOpEffect(new BlurFilter()));
}
public void repaint() {
setDirty(true);
}
public void invalidate() {
setDirty(true);
}
public void revalidate() {
setDirty(true);
}
}
}
When it is clicked on JLabel, I want to understand if the click was on "Icon part", or "Text part" of the JLabel, so that different action can be taken. Is there a clever way to do that? Or just I have to solve it relatively with the coordinates of the icon and text?
+1 to #aymeric comment.
What about having two different JLabels
However I do understand why you might be hesitating
negative: requires maintenance of 2 labels.
My clever (:P) solution to this is create your own abstract component - which accepts icon and text as parameters for constructor - by extending JPanel and than adding 2 JLabels to the JPanel, each label has its on MouseAdapter which calls abstract method xxxClicked() (thus any implementing class must override these methods).
Here is an example I made:
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
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.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageIcon ii = null;
try {
//I dont remmend getScaledInstance just used it for speed of code writing
ii = new ImageIcon(ImageIO.read(new URL("http://www.candonetworking.com/java.gif")).getScaledInstance(32, 32, Image.SCALE_SMOOTH));
} catch (Exception ex) {
ex.printStackTrace();
}
MyLabel ml = new MyLabel(ii, "Something") {
#Override
void iconClicked() {
System.out.println("Icon clicked");
}
#Override
void textClicked() {
System.out.println("Text clicked");
}
};
frame.add(ml);
frame.pack();
frame.setVisible(true);
}
});
}
}
abstract class MyLabel extends JPanel {
JLabel iconLabel;
JLabel textLabel;
MouseAdapter iconMA;
MouseAdapter textMA;
public MyLabel(ImageIcon icon, String text) {
iconLabel = new JLabel(icon);
textLabel = new JLabel(text);
iconMA = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
iconClicked();
}
};
textMA = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
textClicked();
}
};
iconLabel.addMouseListener(iconMA);
textLabel.addMouseListener(textMA);
add(iconLabel);
add(textLabel);
}
abstract void iconClicked();
abstract void textClicked();
public JLabel getIconLabel() {
return iconLabel;
}
public JLabel getTextLabel() {
return textLabel;
}
}
I have a main application frame (MainFrame class). On actionperformed event of a JButton, a JPanel (MyJPanel class) is opened by placing it in JDialog. I am not extending JDialog to create MyJPanel class because I might need MyJPanel at other purposes too.
My Problem is I cannot programmatically close the MyJPanel which is displayed in JDialog. Is there anything that I missing? Could you please figure it out?
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class MainFrame extends JPanel {
public MainFrame() {
JButton btnOpenJdialog = new JButton("Open JDialog");
add(btnOpenJdialog);
btnOpenJdialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog jd = new JDialog();
MyJPanel mjp = new MyJPanel(true);//showing in JDialog
jd.setTitle("JDialog");
jd.add(mjp);
jd.pack();
jd.setVisible(true);
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("Test-JFrame");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainFrame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
MyJPanel Class :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JButton;
public class MyJPanel extends JPanel {
private boolean isShownInJDialog = false;
public MyJPanel() {
JButton btnCloseMe = new JButton("Finish Action");
add(btnCloseMe);
btnCloseMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isShownInJDialog) {
MyJPanel.this.setVisible(false);
//how to close the JDialog too.
}
else {
//just hide the content,
MyJPanel.this.setVisible(false);
}
}
});
}
public MyJPanel(boolean isShownInJDialog) {
this();
this.isShownInJDialog = isShownInJDialog;
}
}
UPDATE
I was able to solve this using Howard's answer as :
...
if (isShownInJDialog) {
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
}
...
If I understand your question correctly, you want to close the JDialog which your MyJPanel is contained in but do not have a reference to it?
You may either provide such a reference using the constructor of MyJPanel or change the code inside your ActionListener to
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
which looks up the parent window of your panel without direct reference.