Java OpenGL window closes as soon as it opens - java

I'm using maven to import the jogamp dependencies.
Here is the pom.xml content :
<dependencies>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-main</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-main</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
The code below should create a window.
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
public class Renderer {
private static GLWindow window = null;
public static void init(){
GLProfile.initSingleton();
GLProfile profile = GLProfile.get(GLProfile.GL2);
GLCapabilities caps = new GLCapabilities(profile);
window = GLWindow.create(caps);
window.setSize(640, 360);
window.setResizable(false);
window.setVisible(true);
}
public static void main(String[] args){
init();
}
}
In my case, it creates a window that closes as soon as it opens, and it says Process finished with exit code 0. I followed these instructions, but even by adding the joal and jocl support into maven it did not work.

You need FPSAnimator
public static void init(){
GLProfile.initSingleton();
GLProfile profile = GLProfile.get(GLProfile.GL2);
GLCapabilities caps = new GLCapabilities(profile);
window = GLWindow.create(caps);
window.setSize(640, 360);
window.setResizable(false);
window.setVisible(true);
FPSAnimator animator = new FPSAnimator(window, 30);
animator.start();
}

Related

Neo4j - Lucene - maven shade plugin - Works fine through the Netbeans but doesnt work as jar

I created a maven java application to execute some neo4j queries. I have a class in which neo4j queries are executing and one more in which i made a gui with Swing so i can use a button to execute a query and show the results in a textArea. Everything works fine if i run the project in Netbeans but when i'm using maven shade plugin to create a fat jar of this project, something happens and the neo4j commands dont work. I think that the problem is at lucene jars(from apache folder and neo4j folder) so i used some code in the pom.xml file to fix it, with no luck. Maybe the problem is because of same class name conflict in the classpath.
myJFrame.java
package com.mycompany.neo4jqueries;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
/**
*
* #author Dar309
*/
public class myJFrame extends JPanel {
private JComboBox firstComboBox;
private JTextArea queryTextArea, resultTextArea, infoTextArea;
private String[] comboBoxItems, queryList;
private JButton executeButton;
private Font monosSpacedFont = new Font("monospaced", Font.PLAIN, 12);
private JProgressBar progressBar;
private Task myTask;
private long miliBeforeExec = 0, miliAfterExec = 0, execTime = 0;
public myJFrame() {
super(new BorderLayout());
JPanel firstPanel = new JPanel();
BorderLayout fpL = new BorderLayout();
firstPanel.setLayout(fpL);
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
JPanel topPanel1 = new JPanel();
topPanel1.setLayout(new FlowLayout(FlowLayout.CENTER));
comboBoxItems = new String[]{"1",
"The Top 10 Stack Overflow Users",
"The Top 5 tags That Jon Skeet Used in Asking Questions"};
queryList = new String[]{"match (n) \nreturn head(labels(n)) as label, count(*)",
"match (u:User) \nwith u,size( (u)-[:POSTED]->()) as posts order by posts desc limit 10 \nreturn u.name, posts",
"match (u:User)-[:POSTED]->()-[:HAS_TAG]->(t:Tag) \nwhere u.name = 'Jon Skeet' \nreturn t,count(*) as posts order by posts desc limit 5"};
firstComboBox = new JComboBox(comboBoxItems);
firstComboBox.setSelectedIndex(0);
firstComboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
queryTextArea.setText(queryList[firstComboBox.getSelectedIndex()]);
}
});
topPanel1.add(firstComboBox);
JPanel topPanel2 = new JPanel();
topPanel2.setLayout(new FlowLayout());
queryTextArea = new JTextArea();
queryTextArea.setText(queryList[0]);
queryTextArea.setFont(monosSpacedFont);
queryTextArea.setEditable(false);
JScrollPane queryScrollPane = new JScrollPane(queryTextArea);
queryScrollPane.setPreferredSize(new Dimension(450, 110));
topPanel2.add(queryScrollPane);
JPanel topPanel3 = new JPanel();
topPanel3.setLayout(new FlowLayout());
progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setString("No progress yet");
progressBar.setStringPainted(true);
executeButton = new JButton("Execute");
executeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
executeButton.setEnabled(false);
progressBar.setIndeterminate(true);
firstComboBox.setEnabled(false);
progressBar.setString("Loading...");
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
miliBeforeExec = System.currentTimeMillis();
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
myTask = new Task();
myTask.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress" == evt.getPropertyName()) {
// int progress = (Integer) evt.getNewValue();
// progressBar.setValue(progress);
}
}
});
myTask.execute();
}
});
topPanel3.add(progressBar);
topPanel3.add(executeButton);
topPanel.add(topPanel1, BorderLayout.NORTH);
topPanel.add(topPanel2, BorderLayout.CENTER);
topPanel.add(topPanel3, BorderLayout.SOUTH);
firstPanel.add(topPanel, BorderLayout.NORTH);
JPanel resultPanel = new JPanel();
resultPanel.setLayout(new BorderLayout());
resultTextArea = new JTextArea();
resultTextArea.setFont(monosSpacedFont);
resultTextArea.setText("");
resultTextArea.setEditable(false);
JScrollPane centerScrollPane = new JScrollPane(resultTextArea);
centerScrollPane.setPreferredSize(new Dimension(550, 200));
centerScrollPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0));
resultPanel.add(centerScrollPane, BorderLayout.CENTER);
infoTextArea = new JTextArea();
infoTextArea.setRows(2);
infoTextArea.setFont(monosSpacedFont);
infoTextArea.setEditable(false);
resultPanel.add(infoTextArea, BorderLayout.SOUTH);
firstPanel.add(resultPanel, BorderLayout.CENTER);
add(firstPanel, BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame();
// frame.setSize(650, 550);
frame.setSize(Toolkit.getDefaultToolkit().getScreenSize().width / 2,Toolkit.getDefaultToolkit().getScreenSize().height / 2);
frame.setMinimumSize(new Dimension(frame.getWidth(), frame.getHeight()));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Execute your Neo4j queries");
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
frame.setLocation(x, y);
//Create and set up the content pane.
JComponent newContentPane = new myJFrame();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
class Task extends SwingWorker<Void, Void> {
/*
* Main task. Executed in background thread.
*/
#Override
public Void doInBackground() {
// Random random = new Random();
// int progress = 0;
//Initialize progress property.
setProgress(0);
System.out.println("popo");
resultTextArea.append("popo");
myQuery mq = new myQuery();
mq.run(myJFrame.this);
resultTextArea.append("metaaaa");
System.out.println("metaaa");
// setProgress(Math.min(progress, 100));
return null;
}
/*
* Executed in event dispatching thread
*/
#Override
public void done() {
Toolkit.getDefaultToolkit().beep();
progressBar.setIndeterminate(false);
executeButton.setEnabled(true);
firstComboBox.setEnabled(true);
// resultTextArea.setCaretPosition(resultTextArea.getText().length());
setCursor(null); //turn off the wait cursor
miliAfterExec = System.currentTimeMillis();
execTime = miliAfterExec - miliBeforeExec;
// execTime += 11140000;
if (execTime < 60 * 1000) {
infoTextArea.setText("Total time: " + (double) (execTime / 1000.000) + "s");
}
// else if(execTime >= (60 * 1000) && execTime < (3600 * 1000) ){
else if (execTime >= (60 * 1000)) {
long temp = execTime;
for (long i = 0; i < execTime / (60 * 1000); i++) {
temp -= (60 * 1000);
}
infoTextArea.setText("Total time: " + (execTime / (60 * 1000)) + ":" + (double) (temp / 1000.000) + "s");
}
Date date = new Date();
infoTextArea.append("\nFinished at: " + date.toString());
progressBar.setString("Done!");
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public JTextArea getResultTextArea() {
return resultTextArea;
}
public JTextArea getQueryTextArea() {
return queryTextArea;
}
}
myQuery.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.mycompany.neo4jqueries;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JFrame;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.helpers.collection.Iterators;
/**
*
* #author Dar309
*/
public class myQuery {
private static final File DB_PATH = new File("D:/IU/Διπλωματική/neo4j-community-3.1.2/data/databases/graph.db");
String resultString;
String columnsString;
String nodeResult;
String rows = "";
void run(myJFrame myFrame) {
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
myFrame.getResultTextArea().append("sdadsdsadsads");
System.out.println("naiiiii");
try (Transaction ignored = db.beginTx();
// Result result = db.execute("match (u:User) with u,size( (u)-[:POSTED]->()) as posts order by posts desc limit 10 return u.name, posts")) {
Result result = db.execute(myFrame.getQueryTextArea().getText() ) ) {
// START SNIPPET: columns
List<String> columns = result.columns();
// END SNIPPET: columns
columnsString = columns.toString();
// resultString = db.execute( "match (u:User) with u,size( (u)-[:POSTED]->()) as posts order by posts desc limit 10 return u.name, posts" ).resultAsString();
resultString = result.resultAsString();
System.out.println("\n\ncolumnsString\n------------------------------------------");
System.out.println(columnsString);
System.out.println("\n\nresultString\n------------------------------------------");
System.out.println(resultString);
myFrame.getResultTextArea().append(resultString);
try {
PrintWriter writer = new PrintWriter("the-file-name.txt", "UTF-8");
writer.print(resultString);
writer.close();
} catch (IOException e) {
// do something
}
}
db.shutdown();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>Neo4jQueries</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
<name>neo4jQueries</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>shaded</shadedClassifierName>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>org.apache.lucene</pattern>
<shadedPattern>shaded_lucene_5_5_0.org.apache.lucene</shadedPattern>
</relocation>
<relocation>
<pattern>org.neo4j</pattern>
<shadedPattern>shaded_neo4j.org.neo4j</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.neo4jqueries.myJFrame</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>neo4j-repo</id>
<name>Neo4j Repository</name>
<url>http://m2.neo4j.org/content/repositories/releases</url>
</repository>
</repositories>
</project>
When i double click on jar, i see the gui and all works fine till myQuery class is called, then no neo4j commands are executing but no error message showed.
Does anyone can help me solve this please?
Your program hardcodes the path to the neo4j DB.
So, if you are not running the jar file on the same machine on which you developed your code, it would not be able to find the DB and will throw an exception.
However, as the doc for InvokeLater says, if the Runnable you pass to it:
throws an uncaught exception the event dispatching thread will unwind
(not the current thread)
That means that your thread will never see any uncaught exceptions unless you explicitly tell Swing to use an exception handler that you provide. See this question and its 2 top-scoring answers for how to do that (depending on which version of Java you are using).

how do i make it possible for a window with buttons program to run?

i have coded this program on an Eclipse development environment and i get only one error that says.
"Error: Could not find or load main class incremental"
please help.
this is prototype for making a simple incremental game.
package pkIncremental;
import javax.swing.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.*;
public class Incremental extends JFrame implements ActionListener
{
public static void main(String[] args)
{
new Incremental();
}
private JLabel lblHead1;
private JLabel lblMessage;
private JButton btnQuit;
private JButton btnObtainMess;
private JButton btnVis;
private JButton btnNotVis;
public Incremental()
{
this.setSize(600,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Incremtial game!");
this.setLayout(null);
Font f = new Font("JSL Ancient", Font.ITALIC,24);
final String M = "The points are bellow";
lblHead1 = new JLabel (M);
lblHead1.setBounds(150, 50, 200, 50);
lblHead1.setFont(f);
this.add(lblHead1);
lblMessage = new JLabel("X");
lblMessage.setOpaque(true);
lblMessage.setBackground(Color.cyan);
lblMessage.setBounds(100, 100, 300, 50);
lblMessage.setFont(f);
lblMessage.setForeground(Color.RED);
this.add(lblMessage);
btnObtainMess = new JButton("Click to get points.");
btnObtainMess.setBounds(100, 150, 300, 50);
btnObtainMess.setFont(f);
btnObtainMess.addActionListener(this);
this.add(btnObtainMess);
btnNotVis = new JButton("not VIsible");
btnNotVis.setBounds(100, 250, 150, 50);
btnNotVis.setFont(f);
btnNotVis.addActionListener(this);
this.add(btnNotVis);
btnVis = new JButton("Visible");
btnVis.setBounds(250, 250, 150, 50);
btnVis.setFont(f);
btnVis.addActionListener(this);
this.add(btnVis);
btnQuit = new JButton("Quit");
btnQuit.setBounds(440,380,100,50);
btnQuit.setFont(f);
btnQuit.addActionListener(this);
this.add(btnQuit);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
String Mess = "Hello from the program";
if (e.getSource() == btnObtainMess)
lblMessage.setText(Mess);
if (e.getSource() == btnVis)
lblMessage.setForeground(Color.RED);
if (e.getSource() == btnNotVis)
lblMessage.setForeground(lblMessage.getBackground());
if (e.getSource() == btnQuit)
System.exit(0);
}
}
Sorry for offtop, but this will help you to run your application correctly:
this.setVisible(true); ->
final Incremental self = this;
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
self.setVisible(true);
}
});
This will allow for your ui event listeners to be independent from main thread.
And nbokmans is right - looks like you run from console like
"java ... incrimental.java" instead of Incremental
Your code worked for me in eclipse using run as -> java application.
If you are trying to run it from command line you must use this command to compile:
javac pkIncremental/Incremental.java
And then this one to run:
java pkIncremental.Incremental

JFrame very small

I'm following a tutorial and made a JFrame, but it's very tiny. Iv'e searched for this problem on this site, but nothing has helped. Does anybody know the problem? I did it exactly like the tutorial, and it worked for him! I'll post a picture of it also.
Here is the code:
package net.trails.std;
import java.applet.Applet;
import java.awt.Dimension;
import java.awt.Image;
import javax.swing.JFrame;
public class Core extends Applet implements Runnable {
private static final long serialVersionUID = 1L;
private static JFrame frame;
public static double dY = 0, dX = 0;
public static final int res = 1;
public static int dir = 0;
public static boolean moving = false;
public static boolean run = false;
private Image screen;
public static Dimension screenSize = new Dimension(700, 560);
public static Dimension pixel = new Dimension(screenSize.width, screenSize.height);
public static Dimension size;
public static String name = "Trails";
public Core(){
}
public static void main(String[] args) {
Core core = new Core();
frame = new JFrame();
frame.add(core);
size = new Dimension(frame.getWidth(), frame.getHeight());
frame.setSize(700, 560);
frame.setTitle(name);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
core.start();
}
public void run() {
}
}
Get rid of the line with frame.pack().
This packs the frame in as small as possible while still fitting everything inside it. You have nothing inside it yet (since core is nothing).
You're calling frame.pack() with no sized components in your JFrame. This is going to squish the whole thing down to the tiny window you currently have.
Look at the docs for pack():
http://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#pack()
Basically, you need to call setSize() in your Core class (which is an applet).

Input method removes transparent effect from JFrame in Swing

import javax.swing.JFrame;
import javax.swing.JTextField;
import com.sun.awt.AWTUtilities;
#SuppressWarnings("serial")
public class TranslucentIssueTest extends JFrame
{
public static void main(String[] args)
{
(new TranslucentIssueTest()).setVisible(true);
}
public TranslucentIssueTest()
{
super();
setUndecorated(true);
setLayout(null);
setSize(300, 300);
AWTUtilities.setWindowOpaque(this, false);
JTextField box = new JTextField();
box.setBounds(30, 150, 100, 25);
add(box);
}
}
The code above creates a textfield on transparent frame.
But when I typed some Chinese characters into the box using an input method, transparent effect was removed automatically. Is there anything wrong with my code?
Thanks in advance.
I ran into what appears to be the same issue and thought I'd post my solution for anyone who finds this question while searching. The problem seems to be due to a bug in the DirectDraw pipeline in Swing. I'm using an older version of Java 7 (update 5), so it's possible that this has been fixed in one of the later releases.
The problem doesn't seem to be with the IME specifically, but rather with the rendering calls that get made by the text field while the IME is active.
The simplest way to work around the problem is to just disable DirectDraw rendering by making the following call before any GUI code is run:
System.setProperty("sun.java2d.noddraw", "true");
If you'd rather not disable DirectDraw rendering entirely, you can work around the specific JTextField issue by overriding its paintComponent method to write to a buffer as in the example below.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class Test {
public static class JTextField2 extends JTextField {
private static final long serialVersionUID = 1L;
private BufferedImage buffer = null;
#Override public void paintComponent(Graphics g) {
Component window = this.getTopLevelAncestor();
if (window instanceof Window && !((Window)window).isOpaque()) {
// This is a translucent window, so we need to draw to a buffer
// first to work around a bug in the DirectDraw rendering in Swing.
int w = this.getWidth();
int h = this.getHeight();
if (buffer == null || buffer.getWidth() != w || buffer.getHeight() != h) {
// Create a new buffer based on the current size.
GraphicsConfiguration gc = this.getGraphicsConfiguration();
buffer = gc.createCompatibleImage(w, h, BufferedImage.TRANSLUCENT);
}
// Use the super class's paintComponent implementation to draw to
// the buffer, then write that buffer to the original Graphics object.
Graphics bufferGraphics = buffer.createGraphics();
try {
super.paintComponent(bufferGraphics);
} finally {
bufferGraphics.dispose();
}
g.drawImage(buffer, 0, 0, w, h, 0, 0, w, h, null);
} else {
// This is not a translucent window, so we can call the super class
// implementation directly.
super.paintComponent(g);
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
final JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setBackground(new Color(96, 128, 160, 192));
JTextField textField = new JTextField2();
JButton exitButton = new JButton("Exit");
exitButton.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
frame.dispose();
}
});
frame.add(exitButton, BorderLayout.PAGE_START);
frame.add(textField, BorderLayout.PAGE_END);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

How to click through JGlassPane With MouseListener to UI behind it

I have a JFrame and a bunch of JComponents on top of the JFrame.
I need to make use of the JGlassPane and I used this implementation to set it up.
JPanel glass = new JPanel();
frame.setGlassPane(glass);
glass.setVisible(true);
glass.setOpaque(false);
After doing so I can't select any JButtons or other JComponents under the JGlassPane.
Is there a way to have only the components on the GlassPane selectable while still having the ability to select components under the GlassPane?
Edit I forgot to mention (not knowing this would be relevant) that I did attach both a MouseListener and a MouseMotionListener to the glass pane. Is there a way to pass the Mouse Events to other components and only use them when needed?
Make your mouseListener dispatch the events it doesn't want to handle.
The example code below is mixed, using the nice SSCCE by #whiskeyspider and the tutorial (BTW: looking into the tutorial is a good starter for solving problems :-)
ml = new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
dispatchEvent(e);
}
// same for all methods
// ....
private void dispatchEvent(MouseEvent e) {
if (isBlocked)
return;
Point glassPanePoint = e.getPoint();
Container container = frame.getContentPane();
Point containerPoint = SwingUtilities.convertPoint(glass,
glassPanePoint, container);
if (containerPoint.y < 0) { // we're not in the content pane
// Could have special code to handle mouse events over
// the menu bar or non-system window decorations, such as
// the ones provided by the Java look and feel.
} else {
// The mouse event is probably over the content pane.
// Find out exactly which component it's over.
Component component = SwingUtilities.getDeepestComponentAt(
container, containerPoint.x, containerPoint.y);
if (component != null) {
// Forward events to component below
Point componentPoint = SwingUtilities.convertPoint(
glass, glassPanePoint, component);
component.dispatchEvent(new MouseEvent(component, e
.getID(), e.getWhen(), e.getModifiers(),
componentPoint.x, componentPoint.y, e
.getClickCount(), e.isPopupTrigger()));
}
}
}
};
glass.addMouseListener(ml);
glassButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (isBlocked) {
// glass.removeMouseListener(ml);
glassButton.setText("Block");
} else {
// ml = new MouseAdapter() { };
// glass.addMouseListener(ml);
glassButton.setText("Unblock");
}
isBlocked = !isBlocked;
}
});
Here's an example of a JButton in the glasspane which when clicked will toggle capturing mouse events (can't click Test button).
public class Test
{
private static boolean isBlocked = false;
private static MouseListener ml;
public static void main(String[] args)
{
JButton button = new JButton("Test");
button.setPreferredSize(new Dimension(100, 100));
final JButton glassButton = new JButton("Block");
JPanel panel = new JPanel();
panel.add(button);
final JPanel glass = new JPanel();
glass.setOpaque(false);
glass.add(glassButton);
final JFrame frame = new JFrame();
frame.setGlassPane(glass);
glass.setVisible(true);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
glassButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (isBlocked) {
glass.removeMouseListener(ml);
glassButton.setText("Block");
} else {
ml = new MouseAdapter() { };
glass.addMouseListener(ml);
glassButton.setText("Unblock");
}
isBlocked = !isBlocked;
}
});
}
}
Another solution without interrupt the Swing event chain, is to use a AWTEventListener instead. I've implemented a BetterGlassPane to be used instead of the regular JPanel glass pane, like so:
JFrame frame = ...; // any JRootPane will do...
BetterGlassPane glass = new BetterGlassPane(frame);
This does also work the "traditional" way, as shown in your question:
JPanel glass = new BetterGlassPane();
frame.setGlassPane(glass);
glass.setRootPane(frame);
Hope this helps. Feel free to clone the project on GitHub or use the Maven dependency:
<dependency>
<groupId>lc.kra.swing</groupId>
<artifactId>better-glass-pane</artifactId>
<version>0.1.3</version>
</dependency>
<repositories>
<repository>
<id>better-glass-pane-mvn-repo</id>
<url>https://raw.github.com/kristian/better-glass-pane/mvn-repo/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
Short, Self Contained, Correct, Example (SSCCE, without obligatory Maven dependency):
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import lc.kra.swing.BetterGlassPane;
public class TestBetterGlassPane {
public static void main(String[] args) {
final JFrame frame = new JFrame("BetterGlassPane Test");
frame.setLayout(null);
frame.setSize(400,300);
frame.setResizable(false);
frame.setLocationByPlatform(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
BetterGlassPane glassPane = new BetterGlassPane(frame.getRootPane()) {
private static final long serialVersionUID = 1L;
#Override protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.setColor(Color.BLACK);
graphics.drawRect(20,160,360,50);
graphics.setFont(graphics.getFont().deriveFont(Font.BOLD));
graphics.drawString("I'm the glass pane, click me!",120,190);
}
};
glassPane.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent event) {
if(new Rectangle(20,180,360,50).contains(event.getPoint()))
JOptionPane.showMessageDialog(frame,"I'm the glass pane!");
}
});
glassPane.setLayout(null);
ActionListener defaultActionListener = new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(frame,
((JButton)event.getSource()).getText());
}
};
JButton frameButton = new JButton("I'm on the frame!");
frameButton.addActionListener(defaultActionListener);
frameButton.setBounds(20,20,360,50);
frame.add(frameButton);
JButton glassPaneButton = new JButton("I'm on the glass pane!");
glassPaneButton.addActionListener(defaultActionListener);
glassPaneButton.setBounds(20,90,360,50);
glassPane.add(glassPaneButton);
frame.setVisible(true);
}
}

Categories