I have a Java program which is launched from a browser, running with various java.awt.Button buttons. When clicked, it's fine. But when a key is pressed that corresponds to that button, Windows makes the "Default Beep" sound.
The buttons are created like this:
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.io.*;
import java.awt.Panel;
import java.awt.Button;
import java.awt.Font;
import java.awt.event.*;
import java.lang.Integer;
public class buttonPne extends Panel implements ActionListener, constants {
private pClient parent = null;
private labelPne buttonLabel[] = new labelPne[8];
private Panel buttonPanel[] = new Panel[8];
public Button theButtons[] = new Button[8];
private boolean buttonStatus[] = new boolean[8];
public buttonPne(pClient c) {
parent = c;
this.setLayout(new GridLayout(1, 8, 1, 0));
for (int i = 0; i < 8; i++) {
buttonLabel[i] = new labelPne(parent);
buttonLabel[i].setSize(9, 9);
theButtons[i] = new Button();
theButtons[i].setFont(ButtonFont);
theButtons[i].setActionCommand(Integer.toString(i));
theButtons[i].addActionListener(this);
theButtons[i].addKeyListener(parent);
buttonPanel[i] = new Panel();
buttonPanel[i].setBackground(backgroundColor);
buttonPanel[i].setLayout(new BorderLayout());
buttonPanel[i].add("North", theButtons[i]);
buttonPanel[i].add("South", buttonLabel[i]);
this.add(buttonPanel[i]);
}
Deactivate();
}
The key presses are handled like this:
import java.awt.event.KeyEvent;
...
public class pClient extends Applet implements KeyListener, constants {
...
f.addKeyListener(this);
...
public void keyPressed(KeyEvent evt) {
int theKey;
theKey = evt.getKeyCode();
switch(theKey) {
case KeyEvent.VK_1:
case KeyEvent.VK_F1:
buttons.DoButton(0);
break;
...
public void DoButton(int theNumber) {
if (buttonStatus[theNumber]) {
if (parent.pollSendFlag(BUTTONS)) {
parent.chat.takeFocus();
parent.compass.Deactivate();
Deactivate();
}
}
return;
}
How can I stop the default beep from happening on key presses?
Use Swing components instead of AWT components.
Related
So I am trying to code a jeopardy game, but the catch is that I am only trying to assign my buttons to 1 action listener so that all buttons function on their own yet work from 1 action listener.
I've tried a lot, nothing works!
package jep;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class jep implements ActionListener{
public JButton[][] t = new JButton[6][6];
public static void main(String[] args) {
new jep();
}
static int n = 100;
public jep() {
JFrame frame = new JFrame("Jeopardy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1920,1080);
frame.setLayout(new GridLayout(6, 5));
frame.setVisible(true);
for (int r = 0; r < 6; r++) {
for (int c = 0; c < 5; c++) {
String vakue = String.valueOf(n);
t[r][c] = new JButton(vakue);
t[r][c].setBackground(Color.BLUE);
t[r][c].setForeground(Color.YELLOW);
t[r][c].addActionListener(this);
frame.add(t[r][c]);
}
n = n +300;
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
I am trying to get it so that i can click multiple buttons using only 1 action listener but all i can get is a grid
Here is the corrected code with print to console on button press. Please, check the comments in the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Jep implements ActionListener { // class name has to start with a capital letter
int i = 6;
int j = 5;
public JButton[][] t = new JButton[i][j];
public static void main(String[] args) {
new Jep();
}
static int n = 100;
public Jep() {
JFrame frame = new JFrame("Jeopardy");
JPanel[][] panelHolder = new JPanel[i][j]; // use panels to add you buttons, check this for details:
// https://stackoverflow.com/questions/2510159/can-i-add-a-component-to-a-specific-grid-cell-when-a-gridlayout-is-used
frame.setLayout(new GridLayout(i, j));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1920, 1080);
frame.setVisible(true);
for (int r = 0; r < 6; r++) {
for (int c = 0; c < 5; c++) {
String vakue = String.valueOf(n);
t[r][c] = new JButton(vakue);
t[r][c].setBackground(Color.BLUE);
t[r][c].setForeground(Color.BLACK);
t[r][c].addActionListener(this);
panelHolder[r][c] = new JPanel();
panelHolder[r][c].add(t[r][c]);
frame.add(panelHolder[r][c]);
n = n + 300;
}
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("press, value = " + arg0.getActionCommand()); // here is a simple system out log statement
}
}
Output(when you press several buttons):
press, value = 100
press, value = 400
press, value = 700
press, value = 1000
press, value = 1300
press, value = 1600
App Winodow:
Hope this will help.
You can use AbstractButton (superclass of JButton).setActionCommand, and then in your listener using action command you can figure out your row and column
Instead of creating a 6 x 6 array of JButtons, you ought to use JTable, set the renderer to render your cells values as buttons (or something else) and as recommended here add a listSelectionListener to the tablemodel to get the row and the column values on click. As recommended here: Get position of Click JTable while using Cell renderer
Learning JTable and how to use renders etc can take a little time. But I assume that for this question you are in a learning environment anyway, that this is not something being done for business, or? So I would recommend you take the time to learn JTable. You will end up being much happier with your final product I promise you.
the problem is in the line public class keyPressed implements KeyListener{
it tells me to make it abstract but i know that is not needed. Please any advice to why this is so or how to properly make this work thanks
package GUI;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import Data.TileList;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class MainUI implements Runnable {
public JPanel gameGrid = new JPanel();
private JFrame gameBoard;
private int row = 4;
private int col = 1;
int boardSize = row * col;
public MainUI(){
}
#Override
public void run(){
gameBoard = new JFrame("BrickGame");
JButton st = new JButton("Start");
Font fontst0 = st.getFont();
Font fontst1 = fontst0.deriveFont(Font.BOLD, fontst0.getSize()*14);
st.setFont(fontst1);
gameBoard.add(gameGrid);
gameGrid.setLayout(new GridLayout(2,1));
st.addActionListener(new StartGame(this));
gameGrid.add(st);
JLabel txt = new JLabel();
txt.setText("<HTML><body><H1>Instructions</H1><p>Click the 'start' button to start the game" +
"<br>Type the letters in the bricks to make a bric dissapear. After all bricks are gone the game is over.<p></body></HTML>");
gameGrid.add(txt);
gameBoard.setVisible(true);
gameBoard.pack();
}
public void StartGame(){
gameGrid.removeAll();
gameGrid.setLayout(new GridLayout(row,col));
gameBoard.add(gameGrid);
for(int i = 0; i < boardSize; i++){
//String x = TileList.Letters[i] + "";
//JButton tile = new JButton(x);
JButton tile = new JButton(new TileList(TileList.Letters[i]).getLetter() + "");
tile.setBackground(Color.red);
gameGrid.add(tile);
}
gameBoard.setFocusable(true);
//here i am trying to addd the class of keypressed to the jframe.
gameBoard.addKeyListener(new keyPressed());
gameBoard.add(gameGrid);
gameBoard.pack();
}
}
package GUI;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
//the problem is in the implements line below it tells me to make it abstract but that is not needed.
public class keyPressed implements KeyListener{
public keyPressed(){
}
public void keyTyped(KeyEvent e) {
}
}
The compiler is telling you exactly what's wrong. You have a class implementing an interface, and you're not implementing all the interface methods. You need to fix this by adding the third method, keyReleased. The API would tell you which methods you need, and in the future you will want to have a look there when you have similar problems.
public class keyPressed implements KeyListener{
public keyPressed(){
}
public void keyTyped(KeyEvent e) {
}
}
KeyListener has three methods and you have implemented only 2 .Either implement the remaining methods or mark your class as abstract.
So if you want to use only 2 methods the you have to use keyAdapterhere:
public class adapter implements KeyAdapter{
#Override
public keyPressed(KeyEvent key){
//action...
}
#Override
public void keyTyped(KeyEvent key) {
//action
}
}
Note that:
The KeyListener is interface.
If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.
I am making a vocabulary quiz program and when they click an option, a new window is supposed to pop up saying if they got it right or wrong. That works, but what doesn't show is the button in the window when it gives you the option to go back to the quiz, ruining the chance to continue onto the next question, or even worse, answering the current question.
Here is the main quiz code:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.DataFormatter;
public class SAT extends JFrame implements ActionListener{
private JButton buttonA;
private JButton buttonB;
private JButton buttonC;
private JButton buttonD;
private JPanel panel1;
private JFrame frame1;
private JTextField Text1;
private JLabel label1;
public static final String POOP = "Words3.xls"; //everywhere that there is POOP is the excel sheet
public static String read1(int rowIndex, int colIndex, int a)
{
String value = new String();
HSSFWorkbook wb = null;
try {
wb = new HSSFWorkbook(new FileInputStream(POOP));
} catch (Exception e) {
e.printStackTrace();
}
String sheet2=null;//placeholder
if (a==1){sheet2="SAT";}//one of these for each sheet
if (a==2){sheet2="Test";}
if (a==3){sheet2="vwlvlHU1";}
HSSFSheet sheet = wb.getSheet(sheet2);
HSSFRow row=sheet.getRow(rowIndex-1);
HSSFCell cell=row.getCell(colIndex-1);
DataFormatter formatter = new DataFormatter();
value = formatter.formatCellValue(cell);
return value;
}
private static void saveWorkbook(HSSFWorkbook wb) throws IOException
{
FileOutputStream out = new FileOutputStream(POOP);
wb.write(out);
out.close();
}
public static int RNG1(int a) { //this RNG is used to find the word and random definitions
//RNG code:
int min=1;//1
int max=100;//number of flash cards, highest number, this is a placeholder
if (a==1){max=253;}//we will have one of these statements for each set
if (a==2){max=20;}
if (a==3){max=40;}
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min + 1;//the +1 is so it doesn't choose header, maybe remove
return randomNum;
}
public static int RNG2(int b) {//this RNG will be used to determine which button gets true definition
//RNG code:
int min=1;//1
int max=4;//number of options
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
//FIND THE WORD AND POS
int a=1;//tells methods to look in right set
int rowIndex=RNG1(a);//here is where a random word, pos, and def will be called for
int colIndex=1;//use colIndex=1 to show word
String WORD=read1(rowIndex,colIndex,a);//to pull word
//System.out.println("Word: "+WORD);
int colIndexPOS=2;//POS=part of speech/colIndexPOS=2 for part of speech
String POS=read1(rowIndex,colIndexPOS,a);
//System.out.println("Part of speech: "+POS);
int b=1;//placeholder
int location=RNG2(b);
//if location=1, put it in button 1 and have random definitions for other 3
//if location=2... same for 3 and 4
private String def(){
//TRUE DEFINITION:
int colIndexDEF=3;//DEF= definition/colIndexPOS=3 for definitions
String DEF=read1(rowIndex,colIndexDEF,a);
return DEF;
}
//FAKE DEFINITIONS:
//fake def 1:
private String rdef1(){//THIS BLOCK HAS AN ISSUE. SHOULD NOT BE DIVIDED BY CURLY BRACES BUT IT IS AN ERROR IF THEY ARE NOT THERE. MAYBE MAKE IT A METHOD?
int rowIndex1=0;//null value
int colIndexDEF=3;
String weirdo="WHY";
do{
rowIndex1=RNG1(a);
weirdo=read1(rowIndex1, colIndexPOS, a);
}while(rowIndex1==rowIndex || !weirdo.equals(POS));
String RANDDEF1=read1(rowIndex1, colIndexDEF, a);
return RANDDEF1;
}
//fake def 2:
private String rdef2(){//FIX DOWHILE
int rowIndex2=1;//null value
int colIndexDEF=3;
String POSsave1=null;
//do{
rowIndex2=RNG1(a);
POSsave1=read1(rowIndex2, colIndexPOS, a);
//}while(rowIndex2==rowIndex1 || rowIndex2==rowIndex || !POSsave1.equals(POS));
String RANDDEF2=read1(rowIndex2, colIndexDEF, a);
return RANDDEF2;
}
//fake def 3:
private String rdef3(){//FIX DOWHILE
int rowIndex3=1;//null value
int colIndexDEF=3;
String POSsave2=null;
//do{
rowIndex3=RNG1(a);
POSsave2=read1(rowIndex3, colIndexPOS, a);
//}while(rowIndex3==rowIndex || rowIndex3==rowIndex2 || rowIndex3==rowIndex1 || !POSsave2.equals(POS));
String RANDDEF3=read1(rowIndex3, colIndexDEF, a);
return RANDDEF3;
}
private void createButtonA() {
String definition=null;
if (location==1){
definition=def();
}
if (location==2){
definition=rdef1();
}
if (location==3){
definition=rdef2();
}
if (location==4){
definition=rdef3();
}
buttonA = new JButton(definition);
add(buttonA);
buttonA.setContentAreaFilled(false);
buttonA.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonA.setForeground(Color.blue);
buttonA.setBounds(45,130,295,25);
}
private void createButtonB() {
String definitionB=null;
if (location==1){
definitionB=rdef1();
}
if (location==2){
definitionB=def();
}
if (location==3){
definitionB=rdef3();
}
if (location==4){
definitionB=rdef2();
}
buttonB = new JButton(definitionB);
add(buttonB);
buttonB.setContentAreaFilled(false);
buttonB.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonB.setForeground(Color.blue);
buttonB.setBounds(45,95,295,25);
}
private void createButtonC() {
String definitionC=null;
if (location==1){
definitionC=rdef2();
}
if (location==2){
definitionC=rdef3();
}
if (location==3){
definitionC=def();
}
if (location==4){
definitionC=rdef1();
}
buttonC = new JButton(definitionC);
add(buttonC);
buttonC.setContentAreaFilled(false);
buttonC.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonC.setForeground(Color.blue);
buttonC.setBounds(45,60,295,25);
}
private void createButtonD() {
String definitionD=null;
if (location==1){
definitionD=rdef3();
}
if (location==2){
definitionD=rdef2();
}
if (location==3){
definitionD=rdef1();
}
if (location==4){
definitionD=def();
}
buttonD = new JButton(definitionD);
add(buttonD);
buttonD.setContentAreaFilled(false);
buttonD.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
buttonD.setForeground(Color.blue);
buttonD.setBounds(45,25,295,25);
}
public static void main(String[] args) {
SAT frameTable = new SAT();
//frameTable.SAT(); //Creating Frame
frameTable.createButtonA(); //Creating Button 1
frameTable.createButtonB(); //Creating Button 2
frameTable.createButtonC();//Creating button 3
frameTable.createButtonD();//Creating button 3
}
public SAT() {//problem
Container window = getContentPane();
window.setLayout(new FlowLayout() ); //using the FlowLayout manager
setSize(400,250); //setting the size of the initial box
setVisible(true); //allows for manual size changing of the box
setTitle("FlaQuiZ"); //Title for the GUI
window.setBackground(Color.white);
setLocation(500,280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Allows us to actually exit when we click the "X"
panel1 = new JPanel(new GridLayout());
add(new JLabel("Choose the option that best fits this word: "+WORD));
//add(new JLabel(""));
}
public void actionPerformed(ActionEvent i) {
if ( location==1 && i.getSource() == buttonA || location==2 && i.getSource()==buttonB || location==3 && i.getSource()==buttonC || location==4 && i.getSource()==buttonD) {
GRATS congrats =new GRATS();
congrats.setVisible(true);
dispose();
}
else{
NO bad =new NO();
bad.setVisible(true);
dispose();
}
}
}
And then here would be the code if they got it wrong, where the button should appear to give the option to go back:
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class NO extends JFrame implements ActionListener{
private JButton NOB;
private JPanel panel3;
public NO() {
Container window = getContentPane();
window.setLayout(new FlowLayout() ); //using the FlowLayout manager
setSize(275,160); //setting the size of the initial box
setVisible(true); //allows for manual size changing of the box
setTitle("Flaquiz"); //Title for the GUI
window.setBackground(Color.white);
setLocation(500,280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Allows us to actually exit when we click the "X"
JPanel panel3 = new JPanel(new GridLayout());
add(new JLabel("Uh oh, you got it wrong!"));
//add(new JLabel(""));
}
public static void main(String[] args) {
NO bad = new NO();
//frameTable.SAT(); //Creating Frame
bad.createbuttonNOB(); //Creating Button 1
}
private void createbuttonNOB() {
NOB = new JButton("Go Back");
add(NOB);
NOB.setContentAreaFilled(false);
NOB.addActionListener((ActionListener) this);//this allows an action to be performed when the button is pressed
NOB.setForeground(Color.blue);
NOB.setBounds(45,45,45,45);
}
public void actionPerformed(ActionEvent i) {
if (i.getSource() == NOB ) {
SAT goback =new SAT();
goback.setVisible(true);
dispose();
}
}
}
I may be missing something, but it seems you add the button directly to the JFrame even though you have a JPanel occupying the whole frame. Why not add the button to the JPanel?
Side Note: In the NO constructor, SetVisible doesn't determine whether or not you can manually change size. That's controlled by things like SetMaximumSize, SetMinimumSize, and SetResizable.
I have 3 clasess : Loader, MyDialog and TEST(with main method). (for code see below)
Everything I want to achieve is create simple dialog with JLabel and JProgressBar, which will notify user about how much time remains to show MyDialog. MyDialog is Jdialog with time consuming operation in constructor (loading data from database etc.).
In code below is model situation. When "MyDialog" is created by main (constant BY_USER is false), everything working exactly i want to. But when i make dialog with button , and instance of MyDialog is created after button press (constant BY_USER is true), Loader is blank white form. It looks like is not completed.
Loader is extending Thread, so i suppose that problem will be in threading (event dispatch thread)? I dont know, what is wrong and how fix it. Please help.
Thanks and sorry for my English.
CLASS TEST :
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class TEST {
public static final boolean BY_USER = false;
public static void main(String[] args) {
if (BY_USER) {
JFrame mainDialog = new JFrame("Main");
JButton show = new JButton("Show MyDialog");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MyDialog dialog = new MyDialog();
}
});
mainDialog.add(show);
mainDialog.setLocationRelativeTo(null);
mainDialog.setMinimumSize(new Dimension(160, 80));
mainDialog.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainDialog.setVisible(true);
} else {
MyDialog dialog = new MyDialog();
}
}
}
CLASS MyDialog :
package test;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class MyDialog extends JFrame{
public MyDialog() {
super();
// making loader with title, first message and count of steps of operation
Loader loader = new Loader("Loader", "First showed message", 100);
loader.ShowLoader();
// time-consuming operation (loading data from database etc.).
// for clarity replaced with for statement
int j=0;
for(int i=0; i<Integer.MAX_VALUE; i++)
{
j++;
if(j==Integer.MAX_VALUE/100){
// updating loader message and progress bar value
loader.NewAction(Integer.MAX_VALUE - i+"");
j=0;
}
}
// closing loader
loader.DestroyLoader();
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
CLASS Loader:
package test;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
public class Loader extends Thread{
private JDialog dialog;
private JLabel message = new JLabel("", SwingConstants.CENTER);
private JProgressBar progressBar = new JProgressBar(0, 100);
private String newMessage;
private double percentForStep;
private int remainingSteps;
public Loader(String taskName, String firstMessage, int steps) {
this.remainingSteps = steps-1;
dialog = new JDialog((Dialog) null, taskName);
dialog.setLayout(new BorderLayout(15, 15));
dialog.add(message, BorderLayout.CENTER);
dialog.add(progressBar, BorderLayout.SOUTH);
message.setText(firstMessage);
percentForStep = 100 / steps;
}
public void ShowLoader()
{
dialog.setMinimumSize(new Dimension(400,120));
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
this.start();
}
public void DestroyLoader(){
dialog.dispose();
this.interrupt();
}
public void NewAction(String newMessage){
this.newMessage = newMessage;
this.remainingSteps--;
Lock.changed = true;
}
public int RemainingStepsCount()
{
return remainingSteps;
}
#Override
#SuppressWarnings({"CallToThreadYield", "SleepWhileInLoop"})
public void run() {
do{
synchronized (Lock.class) {
if (Lock.changed) {
Lock.changed = false;
this.message.setText(newMessage);
this.progressBar.setValue((int)(100-(remainingSteps*percentForStep)));
dialog.repaint();
}
dialog.repaint();
}
}while(true);
}
}
class Lock{
static boolean changed = false;
}
Look to SwingWorker and his use; I think it can help you to solve the problem.
I have code taken from here that would allow selection of a JTree Row by clicking anywhere on the row. it works fine in single row selection mode. However, I am not sure how to modify it in order to handle multiple row selections. how do I distinguish the case when user is make a multiple selection(eg. by holding down the shift or control button while making a left mouse click on a row)?
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
#SuppressWarnings("serial")
public class NavTree extends JTree {
private boolean fWholeRowSelectionEnabled;
private MouseListener fRowSelectionListener;
final NavTree fThis;
public NavTree(TreeNode rootNode) {
super(rootNode);
fThis = this;
init();
}
public NavTree() {
fThis = this;
init();
}
private void init() {
//setCellRenderer(new NavTreeCellRenderer());
fRowSelectionListener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
int closestRow = fThis.getClosestRowForLocation(
e.getX(), e.getY());
Rectangle closestRowBounds = fThis.getRowBounds(closestRow);
if(e.getY() >= closestRowBounds.getY() &&
e.getY() < closestRowBounds.getY() +
closestRowBounds.getHeight()) {
if(e.getX() > closestRowBounds.getX() &&
closestRow < fThis.getRowCount()){
fThis.setSelectionRow(closestRow);
}
} else
fThis.setSelectionRow(-1);
}
}
};
setWholeRowSelectionEnabled(true);
}
public void setWholeRowSelectionEnabled(boolean wholeRowSelectionEnabled) {
fWholeRowSelectionEnabled = wholeRowSelectionEnabled;
if (fWholeRowSelectionEnabled)
addMouseListener(fRowSelectionListener);
else
removeMouseListener(fRowSelectionListener);
}
public boolean isWholeRowSelectionEnabled() {
return fWholeRowSelectionEnabled;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
root.add(new DefaultMutableTreeNode("Child 1"));
root.add(new DefaultMutableTreeNode("Child 2"));
root.add(new DefaultMutableTreeNode("Child 3"));
NavTree tree = new NavTree(root);
frame.add(tree);
frame.setSize(200, 300);
frame.setVisible(true);
}
}
Use the modifier key information of the MouseEvent. See MouseEvent#getModifiersEx for more information
PS: the listener registration contains a bug
public void setWholeRowSelectionEnabled(boolean wholeRowSelectionEnabled) {
fWholeRowSelectionEnabled = wholeRowSelectionEnabled;
if (fWholeRowSelectionEnabled)
addMouseListener(fRowSelectionListener);
else
removeMouseListener(fRowSelectionListener);
}
Setting the property wholeRowSelectionEnabled to true should register the listener only one time. Your code would add the listener again and again if the property is set to true multiple times. What I mean is that the property setter should be idempotent.
A quickfix could be to remove it first and add it if enabled
public void setWholeRowSelectionEnabled(boolean wholeRowSelectionEnabled) {
removeMouseListener(fRowSelectionListener);
fWholeRowSelectionEnabled = wholeRowSelectionEnabled;
if (fWholeRowSelectionEnabled)
addMouseListener(fRowSelectionListener);
}