another problem. I wanted to make doubleclick on JTable which open new window with form. So finally i made it this way:
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent event){
int viewRow = table.getSelectedRow();
if(viewRow < 0)
System.out.println("LOL");
else{
final int modelRow = table.convertRowIndexToModel(viewRow);
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if(e.getClickCount() == 2)
try {
new BookForm();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
}
});
It works, but not perfect. First time when i doubleclick on JTable it opens 2 windows (why not one?), next time it opens 4 windows, next another 6 windows, etc. Any ideas? Maybe i should have to use different method? Thanks for help!
Take a second to look over your code...
Each time the selection changes, you add a new MouseListener
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent event){
int viewRow = table.getSelectedRow();
if(viewRow < 0)
System.out.println("LOL");
else{
// You add a new mouse listener...
final int modelRow = table.convertRowIndexToModel(viewRow);
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if(e.getClickCount() == 2)
try {
new BookForm();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
}
});
So, when you "finally" double click a row, you will have 1-n MouseListeners registered against the table...
You could just get rid of the selection listener and simple add the MouseListener directly to the table...
table.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if(e.getClickCount() == 2)
int selectedRow = table.getSelectedRow();
if (selectedRow > -1) {
int modelRow = table.convertRowIndexToModel(selectedRow);
try {
new BookForm();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
Also take a look at The Use of Multiple JFrames: Good or Bad Practice? before you bomb bard your user with lots of new windows...
Related
Can we enable a jcomboBox according to a click on an item of another jcomboBox after the execution of our jFrame? is it possible ?
JComboBox comboBox_1 = new JComboBox();
comboBox_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
ind = comboBox_1.getSelectedIndex();
System.out.println(ind);
if(ind==1) {
comboBox_4.setEnabled(true);
}
} catch (Exception e1) {
}
});
I'm trying to catch the event when the small "minimize" or "maximize" arrows of a JSplitPane's divider are clicked.
I found a way to listen to a click elsewhere on the divider bar. Something like :
SplitPaneUI spui = splitPane.getUI();
if (spui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) spui).getDivider().addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// do something...
}
});
}
But is there a way to listen to clicks on the arrows?
I'm trying to catch the event when the small "minimize" or "maximize" arrows of a JSplitPane's divider are clicked.
Maybe you could add a PropertyChangeListener to the JSPlitPane and listen for dividerLocation changes (assuming you don't care if the divider was dragged or "one clicked" to the start or end). Then you can check if the divider location is at 0 or the maximum.
splitPane.addPropertyChangeListener("dividerLocation", this);
...
public void propertyChange(PropertyChangeEvent e)
{
// Get the new divider location of the split pane
int location = ((Integer)e.getNewValue()).intValue();
if (location == 0)
// do something
else if (location == splitPane.getMaximumDividerLocation())
// do something else
}
If you do care about the difference between dragging and clicking, then maybe you can compare the old/new values and look for a change in the location greater than a specified value.
Another option is to get the button from the divider:
JSplitPane splitPane = (JSplitPane)e.getSource();
BasicSplitPaneUI ui = (BasicSplitPaneUI)splitPane.getUI();
BasicSplitPaneDivider divider = ui.getDivider();
JButton button1 = (JButton)divider.getComponent(0)
Now you can add another ActionListener to the button to do your custom code.
Reflection is the Only way I guess to listen to One Touch Expandable Buttons
Just pass addSplitPaneListener and it is done.
public void addSplitPaneListener(JSplitPane splitPane) {
addSplitPaneListener("leftButton", splitPane);
addSplitPaneListener("rightButton", splitPane);
}
public void addSplitPaneListener(String button, JSplitPane splitPane) {
try {
Field field = BasicSplitPaneDivider.class.getDeclaredField(button);
field.setAccessible(true);
JButton onetouchButton = (JButton) field.get(((BasicSplitPaneUI) splitPane.getUI()).getDivider());
onetouchButton.setActionCommand(button);
onetouchButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
buttonClicked(e);
}
});
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
//Logger.getLogger(NewJFrame1.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void buttonClicked(ActionEvent e) {
System.out.println("Clicked " + e.getActionCommand());
}
Here is a derived class that deals with expanding/hiding either using the one touch expander and/or an additional keylistener bound to a certain key to hide/unhide the RIGHT panel. Doing it for the left should easy to adapt ;)
Interestingly on Linux the right part will never get its theoretical maximum value but will be one less (BUGCLICKONETOUCH). Didn't test if this is also true on Windows.
import java.awt.Component;
import javax.swing.JSplitPane;
public class JToggleSplitPane extends JSplitPane {
private int restoreWidth = -1;
private final static int BUGCLICKONETOUCH = 1;
public JToggleSplitPane(int splittype, Component c1, Component c2) {
super(splittype, c1, c2);
setOneTouchExpandable(true);
}
public void toggle() {
try {
if (getDividerLocation() < getWidth() - getDividerSize() - BUGCLICKONETOUCH) {
restoreWidth = getWidth() - getDividerSize() - getDividerLocation();
setDividerLocation(1.0d);
} else {
setDividerLocation(getWidth() - getDividerSize() - restoreWidth);
}
updateUI();
doLayout();
} catch (Exception e) {
e.printStackTrace();
}
}
public void doLayout() {
super.doLayout();
if (restoreWidth == -1) {
restoreWidth = rightComponent.getWidth();
}
}
}
I am attempting to load a saved file from JFileChooser using an actionListener. Here is a snippet of code.
class chooserListener implements ActionListener{
public void actionPerformed (ActionEvent e)
{
if (e.getSource() instanceof JFileChooser){
JFileChooser openFile = (JFileChooser)e.getSource();
String command = e.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)){
File selectedFile = openFile.getSelectedFile();
loadSavedGame(selectedFile);
System.out.print("clicked open file");
tp.setSelectedIndex(0);
}
else if (command.equals(JFileChooser.CANCEL_SELECTION)) {
System.out.print("tester");
tp.setSelectedIndex(0);
}
}
}
}
chooser.addActionListener(new chooserListener());
public void loadSavedGame(File loadfile) {
int allCells = countCells(loadfile);
setMineGame(allCells);
try {
Scanner loadFile = new Scanner(loadfile);
while (loadFile.hasNextInt()){
for (int i = 0; i < allCells; i++){
mineGame.setCell(i, loadFile.nextInt());
//System.out.print("loading saved game");
}
loadFile.close();
mineGame.repaint();
tp.setSelectedIndex(0);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private int countCells(File countCell) {
int cellCount = 0;
try {
Scanner getCells = new Scanner(countCell);
while (getCells.hasNextInt()){
cellCount++;
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(cellCount);
return cellCount;
}
public void setMineGame(int cells) {
game.removeAll();
mineGame.setDifficulty(cells);
mineGame = new Board(statusbar, difficulty);
game.add(mineGame, BorderLayout.CENTER);
game.add(statusbar, BorderLayout.SOUTH);
frame.validate();
frame.repaint();
}
public void setDifficulty(int cells){
if(cells == 256){
difficulty = 0;
}
if (cells == 676){
difficulty = 1;
}
else difficulty = 2;
}
I feel like I have too many methods for the action listener to do. It is hanging when I click 'open', and the test print line 'System.out.print("clicked open file");' does not print. the rest of my code is really large and I'm not sure how to to an SSCE(?). I'm wondering if anyone can see why my actionListener is hanging? thanks IA
It seems like loadSavedGame(File file) takes a lot of time to execute. As this method is running in the Event Dispatch Thread you feel like your program is hanging and never reaches System.out.print("clicked open file"); line. I'd start testing the time of response for this method in a separate test case
Anyway I'd suggest you a few tips:
1) Note there's no need to implement an ActionListener to do your code. You can simple make this:
JFileChooser chooser = new JFileChooser();
int returnValue = chooser.showOpenDialog(null);
if(returnValue == JFileChooser.APPROVE_OPTION){
//make stuff if approved
} else if(returnValue == JFileChooser.CANCEL_OPTION){
//make stuff if canceled
}
I think it makes people life easier.
2) On the other hand note you have two I/O operations: getting the cells count through countCells(File countCell) method and getting the cells themselves inside loadSavedGame(File loadfile) method. You can do it better reading the file just once:
public List<Integer> getCells(File file){
List<Integer> list = new ArrayList<>();
try {
Scanner getCells = new Scanner(file);
while (getCells.hasNextInt()){
list.add(Integer.valueOf(getCells.nextInt()));
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
return list;
}
}
And make this change in loadSavedGame method:
public void loadSavedGame(File loadfile) {
List<Integer> allCells = getCells(loadfile);
setMineGame(allCells.size());
int index = 0;
for(Integer value : allCells){
mineGame.setCell(index, value);
index++;
}
mineGame.repaint();
tp.setSelectedIndex(0);
}
I have two JLists, jltCategories and jltSubcategories, belonging to the same JPanel. Double clicking on the jltCategories causes the jltSubcategories to be populated with the corresponding subcategories, and jltSubcategories is removed from the JPanel, added back and revalidated.
Double clicking the jltSubcategories AFTER it has been removed/added back does not fire anything. Yet, If I open the program and double click on the jltSubcategories, it will fire its mouse event: It will fire if it hasn't been removed/added back, but it will not fire if it has been removed/added back. Same for jltCategories: if I cause it to be removed/added, it will stop firing. Why is this so? Thank you!
jltCategories.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
jbtNavigate.doClick();
}
}
});
jltSubcategories.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
jbtLoad.doClick();
}
}
});
jbtNavigate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String catName = jltCategories.getSelectedValue();
try {
jpLists.remove(jltSubcategories);
jltSubcategories = new JList<String>(SQL.populateSubcategories(catName));
jpLists.add(jltSubcategories);
jpLists.revalidate();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
});
jbtLoad.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Testing Testing 213");
}
});
It is not enough to revalidate() the view; you must also let the model notify the view that new data is available.
DefaultListModel model = (DefaultListModel ) jltSubcategories.getModel();
model.fireContentsChanged(0, model.getSize());
If this is ineffective, please edit your question to include an sscce that exhibits the problem you describe.
Addendum: It's not clear why you use a MouseListener to effect the update; use a ListSelectionListener, shown here.
I would like to know how can I extend JEditorPane (or any other swing text editing component) to handle rectangle (column) selection mode. It is a well known feature in current text editors where you can select multiple lines (rows) starting from an offset (column) and ending by an offset (column) which look like selecting a rectangle of text, and then what you type will overwrite the selection in each line (row) concurrently.
One idea was to override the selection and create fake selection by highlighting each line in rectangle form by following the mouse events, and keeping track of such information to use it when typing. However, I am not quit sure how to override the selection and track the mouse, nor how to redirect typing to affect each line.
Any help in any form would be appreciated.
Found out this little code snippet, that involves a Custom Caret (to handle the fragmented selection) and Highlighter (to show the fragments):
class MyCaret extends DefaultCaret {
Point lastPoint=new Point(0,0);
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
lastPoint=new Point(e.getX(),e.getY());
}
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
getComponent().getHighlighter().removeAllHighlights();
}
protected void moveCaret(MouseEvent e) {
Point pt = new Point(e.getX(), e.getY());
Position.Bias[] biasRet = new Position.Bias[1];
int pos = getComponent().getUI().viewToModel(getComponent(), pt, biasRet);
if(biasRet[0] == null)
biasRet[0] = Position.Bias.Forward;
if (pos >= 0) {
setDot(pos);
Point start=new Point(Math.min(lastPoint.x,pt.x),Math.min(lastPoint.y,pt.y));
Point end=new Point(Math.max(lastPoint.x,pt.x),Math.max(lastPoint.y,pt.y));
customHighlight(start,end);
}
}
protected void customHighlight(Point start, Point end) {
getComponent().getHighlighter().removeAllHighlights();
int y=start.y;
int firstX=start.x;
int lastX=end.x;
int pos1 = getComponent().getUI().viewToModel(getComponent(), new Point(firstX,y));
int pos2 = getComponent().getUI().viewToModel(getComponent(), new Point(lastX,y));
try {
getComponent().getHighlighter().addHighlight(pos1,pos2,
((DefaultHighlighter)getComponent().getHighlighter()).DefaultPainter);
}
catch (Exception ex) {
ex.printStackTrace();
}
y++;
while (y<end.y) {
int pos1new = getComponent().getUI().viewToModel(getComponent(), new Point(firstX,y));
int pos2new = getComponent().getUI().viewToModel(getComponent(), new Point(lastX,y));
if (pos1!=pos1new) {
pos1=pos1new;
pos2=pos2new;
try {
getComponent().getHighlighter().addHighlight(pos1,pos2,
((DefaultHighlighter)getComponent().getHighlighter()).DefaultPainter);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
y++;
}
}
}
Anyway, I've never run that code (it's Stanislav's).