I have a JTextArea and a JComboBox to allow me to cycle through various open files - the contents of the JTextArea change as I select a different file. I am trying to maintain a different Undo buffer per file and have defined a separate UndoManager per file.
I have created a simpler SSCCE to demonstrate my problem using two buffers, which I call "One" and "Two" - with a simple button to switch between them. Once an UndoableEdit happens, it checks the active buffer and performs an addEdit() on the respective UndoManager. When the "Undo" button is pressed, then it checks canUndo() and performs an undo() on the respective UndoManager. I have a flag called ignoreEdit, which is used when switching between buffers to ignore those edits from being recorded.
If I never switch between the buffers, then I don't have a problem, Undo works as expected. It is only when I switch between the buffers and appear to "break" the Document, does it fail. The following steps can be used to recreate the problem:
In buffer "One", type:
THIS
IS ONE
EXAMPLE
Switch to buffer "Two", type:
THIS
IS ANOTHER
EXAMPLE
Switch to buffer "One" and press the "Undo" button multiple times. After a few Undo operations, the buffer looks like this (with no way for the cursor to select the first two lines). However, the contents of textArea.getText() are correct as per the System.out.println() - so, it looks like a rendering issue?
THIS
THISIS ONE
This can't be the first time that someone has tried to implement independent Undo buffers per file? I am obviously doing something wrong with the Document model and inherently breaking it, but I looking for some advice on how best to fix this?
The code for the SSCCE is included below:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
public class SSCCE extends JFrame implements ActionListener, UndoableEditListener {
private final JLabel labTextArea;
private final JTextArea textArea;
private final JScrollPane scrollTextArea;
private final Document docTextArea;
private final JButton bOne, bTwo, bUndo;
private final UndoManager uOne, uTwo;
private String sOne, sTwo;
private boolean ignoreEdit = false;
public SSCCE(String[] args) {
setTitle("SSCCE - Short, Self Contained, Correct Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 200);
setLocationRelativeTo(null);
labTextArea = new JLabel("One");
getContentPane().add(labTextArea, BorderLayout.PAGE_START);
uOne = new UndoManager();
uTwo = new UndoManager();
sOne = new String();
sTwo = new String();
textArea = new JTextArea();
docTextArea = textArea.getDocument();
docTextArea.addUndoableEditListener(this);
scrollTextArea = new JScrollPane(textArea);
getContentPane().add(scrollTextArea, BorderLayout.CENTER);
JPanel pButtons = new JPanel();
bOne = new JButton("One");
bOne.addActionListener(this);
bOne.setFocusable(false);
pButtons.add(bOne, BorderLayout.LINE_START);
bTwo = new JButton("Two");
bTwo.addActionListener(this);
bTwo.setFocusable(false);
pButtons.add(bTwo, BorderLayout.LINE_END);
bUndo = new JButton("Undo");
bUndo.addActionListener(this);
bUndo.setFocusable(false);
pButtons.add(bUndo, BorderLayout.LINE_END);
getContentPane().add(pButtons, BorderLayout.PAGE_END);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(bOne)) {
if (!labTextArea.getText().equals("One")) {
sTwo = textArea.getText();
ignoreEdit = true;
textArea.setText(sOne);
ignoreEdit = false;
labTextArea.setText("One");
}
}
else if (e.getSource().equals(bTwo)) {
if (!labTextArea.getText().equals("Two")) {
sOne = textArea.getText();
ignoreEdit = true;
textArea.setText(sTwo);
ignoreEdit = false;
labTextArea.setText("Two");
}
}
else if (e.getSource().equals(bUndo)) {
if (labTextArea.getText().equals("One")) {
try {
if (uOne.canUndo()) {
System.out.println("Performing Undo for One");
uOne.undo();
System.out.println("Buffer One is now:\n" + textArea.getText() + "\n");
}
else {
System.out.println("Nothing to Undo for One");
}
}
catch (CannotUndoException ex) {
ex.printStackTrace();
}
}
else if (labTextArea.getText().equals("Two")) {
try {
if (uTwo.canUndo()) {
System.out.println("Performing Undo for Two");
uTwo.undo();
System.out.println("Buffer Two is now:\n" + textArea.getText() + "\n");
}
else {
System.out.println("Nothing to Undo for Two");
}
}
catch (CannotUndoException ex) {
ex.printStackTrace();
}
}
}
}
#Override
public void undoableEditHappened(UndoableEditEvent e) {
if (!ignoreEdit) {
if (labTextArea.getText().equals("One")) {
System.out.println("Adding Edit for One");
uOne.addEdit(e.getEdit());
}
else if (labTextArea.getText().equals("Two")) {
System.out.println("Adding Edit for Two");
uTwo.addEdit(e.getEdit());
}
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SSCCE(args);
}
});
}
}
Previously I had attempted to create a new instance of the Document class (each referencing the same Undo listener) and was going to use JTextArea.setDocument() instead of JTextArea.setText(). However, Document is an interface and can't be instantiated, but after reading the reference that mKorbel posted, I tried this using the PlainDocument class instead, which worked.
I have decided to maintain a HashMap<String, Document> to contain my Document classes and switch between them. When I switch the Document, I don't see the Undo/Redo issue - I suppose as I am no longer breaking the Document.
Updated SSCCE below which now uses JTextArea.setDocument() instead of JTextArea.setText(). This also has the advantage of not requiring the ignoreEdit boolean as setDocument() doesn't trigger an UndoableEditEvent, whereas setText() does. Each Document then references the local classes UndoableEditListener.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
public class SSCCE extends JFrame implements ActionListener, UndoableEditListener {
private final JLabel labTextArea;
private final JTextArea textArea;
private final JScrollPane scrollTextArea;
private final Document docTextArea;
private final JButton bOne, bTwo, bUndo;
private final UndoManager uOne, uTwo;
private Document dOne, dTwo;
public SSCCE(String[] args) {
setTitle("SSCCE - Short, Self Contained, Correct Example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(300, 200);
setLocationRelativeTo(null);
labTextArea = new JLabel("One");
getContentPane().add(labTextArea, BorderLayout.PAGE_START);
uOne = new UndoManager();
uTwo = new UndoManager();
dOne = new PlainDocument();
dTwo = new PlainDocument();
dOne.addUndoableEditListener(this);
dTwo.addUndoableEditListener(this);
textArea = new JTextArea();
docTextArea = textArea.getDocument();
docTextArea.addUndoableEditListener(this);
textArea.setDocument(dOne);
scrollTextArea = new JScrollPane(textArea);
getContentPane().add(scrollTextArea, BorderLayout.CENTER);
JPanel pButtons = new JPanel();
bOne = new JButton("One");
bOne.addActionListener(this);
bOne.setFocusable(false);
pButtons.add(bOne, BorderLayout.LINE_START);
bTwo = new JButton("Two");
bTwo.addActionListener(this);
bTwo.setFocusable(false);
pButtons.add(bTwo, BorderLayout.LINE_END);
bUndo = new JButton("Undo");
bUndo.addActionListener(this);
bUndo.setFocusable(false);
pButtons.add(bUndo, BorderLayout.LINE_END);
getContentPane().add(pButtons, BorderLayout.PAGE_END);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(bOne)) {
if (!labTextArea.getText().equals("One")) {
textArea.setDocument(dOne);
labTextArea.setText("One");
}
}
else if (e.getSource().equals(bTwo)) {
if (!labTextArea.getText().equals("Two")) {
textArea.setDocument(dTwo);
labTextArea.setText("Two");
}
}
else if (e.getSource().equals(bUndo)) {
if (labTextArea.getText().equals("One")) {
try {
if (uOne.canUndo()) {
System.out.println("Performing Undo for One");
uOne.undo();
System.out.println("Buffer One is now:\n" + textArea.getText() + "\n");
}
else {
System.out.println("Nothing to Undo for One");
}
}
catch (CannotUndoException ex) {
ex.printStackTrace();
}
}
else if (labTextArea.getText().equals("Two")) {
try {
if (uTwo.canUndo()) {
System.out.println("Performing Undo for Two");
uTwo.undo();
System.out.println("Buffer Two is now:\n" + textArea.getText() + "\n");
}
else {
System.out.println("Nothing to Undo for Two");
}
}
catch (CannotUndoException ex) {
ex.printStackTrace();
}
}
}
}
#Override
public void undoableEditHappened(UndoableEditEvent e) {
if (labTextArea.getText().equals("One")) {
System.out.println("Adding Edit for One");
uOne.addEdit(e.getEdit());
}
else if (labTextArea.getText().equals("Two")) {
System.out.println("Adding Edit for Two");
uTwo.addEdit(e.getEdit());
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SSCCE(args);
}
});
}
}
This is not an answer per se, but a demonstration of a different way of approaching the same problem.
What this does is wraps the UndoableEditListener in a self managed proxy, which has it's own UndoManager and Document.
Tested this with Java 7 and Java 8:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
import javax.swing.undo.UndoManager;
public class UndoExample {
public static void main(String[] args) {
new UndoExample();
}
private int index = 0;
private Map<String, Undoer> mapUndoers;
private JTextArea ta;
private Undoer current;
public UndoExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
mapUndoers = new HashMap<>(2);
mapUndoers.put("One", new Undoer());
mapUndoers.put("Two", new Undoer());
ta = new JTextArea(4, 20);
ta.setWrapStyleWord(true);
ta.setLineWrap(true);
JButton btnOne = new JButton("One");
JButton btnTwo = new JButton("Two");
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
install(e.getActionCommand());
}
};
btnOne.addActionListener(al);
btnTwo.addActionListener(al);
JButton undo = new JButton("Undo");
undo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (current != null) {
current.undo();
}
}
});
JPanel panel = new JPanel(new GridBagLayout());
panel.add(btnOne);
panel.add(btnTwo);
panel.add(undo);
install("One");
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(ta));
frame.add(panel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void install(String name) {
Undoer undoer = mapUndoers.get(name);
if (undoer != null) {
current = undoer;
undoer.install(ta);
}
}
public class Undoer implements UndoableEditListener {
private UndoManager undoManager;
private Document doc;
public Undoer() {
undoManager = new UndoManager();
doc = createDocument();
doc.addUndoableEditListener(this);
}
public void undo() {
undoManager.undo();
}
public void undoOrRedo() {
undoManager.undoOrRedo();
}
protected Document createDocument() {
return new PlainDocument();
}
public void install(JTextComponent comp) {
comp.setDocument(doc);
}
#Override
public void undoableEditHappened(UndoableEditEvent e) {
undoManager.addEdit(e.getEdit());
}
}
}
Related
I have a code in which I must drag two images from my desktop and drop it on a frame in two draggable buttons. The buttons have already been made on the frame. But while dragging the images, they can only be dragged to one button. The images don't get dragged to the other one. I have made a DragListener class where the dragging methods prevail and the main class DragInitialListener where I have passed objects of class DragButton so that two draggable buttons are created. I have tried everything I could think of, made two DragListener classes, passed the methods differently but the image could only be dragged in one button. I want both the buttons to be able to hold images. Please help me with it. Here's the code that I have made so far:
//This is the main class
public class DragInitialListener extends javax.swing.JFrame {
private volatile int draggedAtX, draggedAtY;
public DragInitialListener() {
initComponents();
Droptargets();
Droptarget();
}
public void Droptarget()
{
DragListener d;
DragButton db = new DragButton();
db.setSize(170,140);
d= new DragListener(db);
DropTarget drop = new DropTarget(this,d);
this.getContentPane().add(db);
}
public void Droptargets()
{
DragListener dd;
DragButton db1 = new DragButton();
db1.setSize(170,140);
dd= new DragListener(db1);
DropTarget drop1 = new DropTarget(this,dd);
this.getContentPane().add(db1);
}
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DragInitialListener().setVisible(true);
}
});
}
// Variables declaration - do not modify
// End of variables declaration
}
//This is the DragListener class
public class DragListener extends JButton implements DropTargetListener
{
JButton imagebutton = new JButton();
// JButton imagebutton1 = new JButton();
private volatile int draggedAtX, draggedAtY;
DragListener(JButton image) {
imagebutton=image;
}
#Override
public void dragEnter(DropTargetDragEvent dtde) {
}
#Override
public void dragOver(DropTargetDragEvent dtde) {
}
#Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
#Override
public void dragExit(DropTargetEvent dte) {
}
#Override
public void drop(DropTargetDropEvent ev) {
ev.acceptDrop(DnDConstants.ACTION_COPY);
Transferable t = ev.getTransferable();
//DropTarget test = (DropTarget) ev.getSource();
DataFlavor[] df= t.getTransferDataFlavors();
for(DataFlavor f:df)
{
try
{
if(f.isFlavorJavaFileListType())
{
List<File> files =(List<File>) t.getTransferData(f);
for(File file : files)
{
displayImage(file.getPath());
}
}
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, ex);
}
}
}
private void displayImage(String path)
{
BufferedImage img = null;
try
{
img =ImageIO.read(new File(path));
}
catch(Exception e)
{
}
ImageIcon icon = new ImageIcon(img);
imagebutton.setIcon(icon);
}
}
Start simple, get one button to work, if you can get one to work, you can get 100 to work
This is a very simple example, which makes use of the transfer API, because you really only care about dropping and not dragging
import java.awt.Component;
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.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 GridBagLayout());
JButton btn = new JButton("Drop here");
btn.setVerticalTextPosition(JButton.BOTTOM);
btn.setHorizontalTextPosition(JButton.CENTER);
btn.setTransferHandler(new ImageTransferHandler());
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public static class ImageTransferHandler extends TransferHandler {
public static final DataFlavor[] SUPPORTED_DATA_FLAVORS = new DataFlavor[]{
DataFlavor.javaFileListFlavor,
DataFlavor.imageFlavor
};
#Override
public boolean canImport(TransferHandler.TransferSupport support) {
boolean canImport = false;
for (DataFlavor flavor : SUPPORTED_DATA_FLAVORS) {
if (support.isDataFlavorSupported(flavor)) {
canImport = true;
break;
}
}
return canImport;
}
#Override
public boolean importData(TransferHandler.TransferSupport support) {
boolean accept = false;
if (canImport(support)) {
try {
Transferable t = support.getTransferable();
Component component = support.getComponent();
if (component instanceof JButton) {
Image image = null;
if (support.isDataFlavorSupported(DataFlavor.imageFlavor)) {
image = (Image) t.getTransferData(DataFlavor.imageFlavor);
} else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
if (files.size() > 0) {
image = ImageIO.read((File) files.get(0));
}
}
ImageIcon icon = null;
if (image != null) {
icon = new ImageIcon(image);
}
((JButton) component).setIcon(icon);
accept = true;
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
return accept;
}
}
}
So, by doing nothing more then changing the layout and replicating the button using
public TestPane() {
setLayout(new GridLayout(5, 5));
for (int index = 0; index < 5 * 5; index++) {
JButton btn = new JButton("Drop here");
btn.setVerticalTextPosition(JButton.BOTTOM);
btn.setHorizontalTextPosition(JButton.CENTER);
btn.setTransferHandler(new ImageTransferHandler());
add(btn);
}
}
I was able to achieve...
Updated...
So apparently I might have misunderstood the question, not the first time. From what's been explained to me, you might want to drag multiple images and have them applied to the buttons. Surprising, the process doesn't change that much.
In this example, I've applied the TransferHandler to the JPanel instead of the button and supplied it the buttons I want updated. You could easily update this to have a variable number of buttons, but I've started with two.
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 GridBagLayout());
JButton left = makeButton("Left");
JButton right = makeButton("Right");
add(left);
add(right);
setTransferHandler(new ImageTransferHandler(left, right));
}
protected JButton makeButton(String text) {
JButton btn = new JButton(text);
btn.setVerticalTextPosition(JButton.BOTTOM);
btn.setHorizontalTextPosition(JButton.CENTER);
return btn;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public static class ImageTransferHandler extends TransferHandler {
public static final DataFlavor[] SUPPORTED_DATA_FLAVORS = new DataFlavor[]{
DataFlavor.javaFileListFlavor,};
private JButton left, right;
public ImageTransferHandler(JButton left, JButton right) {
this.left = left;
this.right = right;
}
#Override
public boolean canImport(TransferHandler.TransferSupport support) {
boolean canImport = false;
for (DataFlavor flavor : SUPPORTED_DATA_FLAVORS) {
if (support.isDataFlavorSupported(flavor)) {
canImport = true;
break;
}
}
return canImport;
}
#Override
public boolean importData(TransferHandler.TransferSupport support) {
boolean accept = false;
if (canImport(support)) {
try {
Transferable t = support.getTransferable();
Image image = null;
if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
List files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
JButton buttons[] = new JButton[]{left, right};
for (int index = 0; index < Math.min(files.size(), 2); index++) {
if (files.size() > 0) {
image = ImageIO.read((File) files.get(index));
ImageIcon icon = null;
if (image != null) {
icon = new ImageIcon(image);
}
buttons[index].setIcon(icon);
}
}
accept = true;
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
return accept;
}
}
}
Now, there are rules you will need to define yourself, for example, what happens when the user only drags a single image? Do you apply it to the first button (as I have) every time, or do you try and find the button without an image and update it? What happens if all the buttons have images? Where does it go then?
Do you reject drags with more than 2 images?
I need to make a slot machine that implements thread in java and jframe
this is what iv'e done so far kindly tell me what i need to do in order make the images change per .5 seconds when i press the the play and stop when i press stop. If all the three images are the same it'll say you won. This is what iv'e got so far how will i change this numbers or text to images in jlabel.
public class MySlotNumber extends JFrame{
private MyJLabel x;
private MyJLabel y;
private MyJLabel z;
private JButton btn;
public MySlotNumber(){
super("ABC");
setLayout(new FlowLayout());
Font font = new Font("arial",Font.ITALIC,50);
x = new MyJLabel();
x.setFont(font);
y = new MyJLabel();
y.setFont(font);
z = new MyJLabel();
z.setFont(font);
btn = new JButton("PLAY");
btn.setFont(font);
add(x);
add(y);
add(z);
add(btn);
final Thread thx = new Thread(x);
final Thread thy = new Thread(y);
final Thread thz = new Thread(z);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("PLAY")){
if(thx.isAlive()){
thx.resume();
thy.resume();
thz.resume();
} else {
thx.start();
thy.start();
thz.start();
}
btn.setText("STOP");
} else {
thx.suspend();
thy.suspend();
thz.suspend();
btn.setText("PLAY");
System.out.println(x.getText());
}
}
});
}
- - - - - - --
public class MyJLabel extends JLabel implements Runnable{
private Random r;
private int ctr;
private final int T = 500;
public MyJLabel(){
setText("0");
ctr = 0;
r= new Random();
}
#Override
public void run() {
while(true){
try {
Thread.sleep(T);
} catch (InterruptedException ex) {
Logger.getLogger(MyJLabel.class.getName()).log(Level.SEVERE, null, ex);
}
//ctr++;
ctr = r.nextInt(9)+1;
setText(String.valueOf(ctr));
}
}
}
Here is one way to put a picture on a JLabel and change it when you click a button. (I am using window builder for eclipse, so it may look a little odd.) It is not recommended you use absolute paths because when you move your project or the file, it breaks (I did this just for proof of concept).
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 1379, 643);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblNewLabel = new JLabel("");
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\Capture.JPG"));
frame.getContentPane().add(lblNewLabel, BorderLayout.CENTER);
JButton btnClickMe = new JButton("click me");
btnClickMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\I'm pretty sure he did.JPG"));
}
});
frame.getContentPane().add(btnClickMe, BorderLayout.EAST);
}
}
this code is only allowing me to reject a string the second time to try to drop in a textArea where there is all ready a string.
public GridLayoutTest() {
JFrame frame = new JFrame("GridLayout test");
connection = getConnection();
try {
statement = (PreparedStatement) connection
result = statement.executeQuery();
while (result.next()) {
byte[] image = null;
image = result.getBytes("image");
JPanel cellPanel = new JPanel(new BorderLayout());
cellPanel.add(cellLabel, BorderLayout.NORTH);
cellPanel.add(droplabel, BorderLayout.CENTER);
gridPanel.add(cellPanel);
}
}
catch (SQLException e) {
e.printStackTrace();}
}
So, two things, first...
public void DropTargetTextArea(String string1, String string2) {
Isn't a constructor, it's a method, note the void. This means that it is never getting called. It's also the reason why DropTargetTextArea textArea = new DropTargetTextArea(); works, when you think it shouldn't.
Second, you're not maintaining a reference to the values you pass in to the (want to be) constructor, so you have no means to references them later...
You could try using something like...
private String[] values;
public DropTargetTextArea(String string1, String string2) {
values = new String[]{string1, string2};
DropTarget dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);
}
And then use something like...
if (values[0].equals(dragContents) || values[1].equals(dragContents)) {
In the drop method.
In your dragEnter, dragOver and dropActionChanged methods you have the oppurtunity to accept or reject the drag action using something like dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); or dtde.rejectDrag();
Updated with test code
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class DragAndDropExample {
public static void main(String[] args) {
ImageIcon ii1 = new ImageIcon("C:\\Users\\Desktop\\home.jpg");
ImageIcon ii = new ImageIcon("C:\\Users\\Desktop\\images (2).jpg");
// Create a frame
JFrame frame = new JFrame("test");
JLabel label = new JLabel(ii);
JLabel label1 = new JLabel(ii1);
JPanel panel = new JPanel(new GridLayout(2, 4, 10, 10));
JLabel testLabel = new DraggableLabel("test");
JLabel testingLabel = new DraggableLabel("testing");
panel.add(testLabel);
panel.add(testingLabel);
panel.add(label);
panel.add(label1);
Component textArea = new DropTargetTextArea("test", "testing");
frame.add(textArea, BorderLayout.CENTER);
frame.add(panel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
DragSource dragSource1;
public DraggableLabel(String text) {
setText(text);
dragSource1 = new DragSource();
dragSource1.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
}
public void dragGestureRecognized(DragGestureEvent evt) {
Transferable transferable = new StringSelection(getText());
dragSource1.startDrag(evt, DragSource.DefaultCopyDrop, transferable, this);
}
public void dragEnter(DragSourceDragEvent evt) {
System.out.println("Drag enter");
}
public void dragOver(DragSourceDragEvent evt) {
System.out.println("Drag over");
}
public void dragExit(DragSourceEvent evt) {
System.out.println("Drag exit");
}
public void dropActionChanged(DragSourceDragEvent evt) {
System.out.println("Drag action changed");
}
public void dragDropEnd(DragSourceDropEvent evt) {
System.out.println("Drag action End");
}
}
public static class DropTargetTextArea extends JLabel implements DropTargetListener {
private String[] values;
public DropTargetTextArea(String string1, String string2) {
values = new String[]{string1, string2};
DropTarget dropTarget = new DropTarget(this, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void dragEnter(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject drag enter");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void dragOver(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject drag over");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void dragExit(DropTargetEvent evt) {
System.out.println("Drop exit");
}
public void dropActionChanged(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject dropActionChanged");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void drop(DropTargetDropEvent evt) {
if (!getText().isEmpty()) {
evt.rejectDrop();
} else {
try {
Transferable transferable = evt.getTransferable();
if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String dragContents = (String) transferable.getTransferData(DataFlavor.stringFlavor);
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
if (values[0].equals(dragContents) || (values[1]).equals(dragContents)) {
System.out.println("Accept Drop");
setText(getText() + " " + dragContents);
evt.getDropTargetContext().dropComplete(true);
} else {
System.out.println("Reject Drop");
}
}
} catch (IOException e) {
evt.rejectDrop();
evt.dropComplete(false);
} catch (UnsupportedFlavorException e) {
}
}
}
}
}
I'm trying to figure out this for ages, starting to wonder if it is possible!
I have a starting window for my app - I need it so that when I click on a button I have created, the window either closes and opens a new window or the window resizes and leaves just the canvas (ready to put new widgets, sprites etc... ).
I know I need a handler event for this but I just can't get the code to work.
Im not quite sure whats your question but i coded a example with a JFrame and 3 Buttons.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class OpenWindowAndResizeWindow
{
private JFrame frame;
private JButton btnOpenNewWindow;
private JButton btnResizeWindow;
private JButton btnRemoveAllButtons;
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
OpenWindowAndResizeWindow window = new OpenWindowAndResizeWindow();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public OpenWindowAndResizeWindow()
{
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize()
{
frame = new JFrame();
frame.setBounds(100, 100, 300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(getBtnOpenNewWindow(), BorderLayout.NORTH);
frame.getContentPane().add(getBtnResizeWindow(), BorderLayout.SOUTH);
frame.getContentPane().add(getBtnRemoveAllButtons(), BorderLayout.CENTER);
frame.setVisible(true);
}
private void openNewWindow()
{
OpenWindowAndResizeWindow newWindow = new OpenWindowAndResizeWindow();
frame.dispose();
}
private void removeButtons()
{
getBtnOpenNewWindow().setVisible(false);
getBtnRemoveAllButtons().setVisible(false);
getBtnResizeWindow().setVisible(false);
}
private void resizeWindow()
{
Rectangle rectangle = frame.getBounds();
rectangle.width = (int)rectangle.getWidth() + 100;
rectangle.height = (int)rectangle.getHeight() + 100;
frame.setBounds(rectangle);
}
private JButton getBtnOpenNewWindow() {
if (btnOpenNewWindow == null) {
btnOpenNewWindow = new JButton("Open new Window");
btnOpenNewWindow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openNewWindow();
}
});
}
return btnOpenNewWindow;
}
private JButton getBtnResizeWindow() {
if (btnResizeWindow == null) {
btnResizeWindow = new JButton("Resize Window");
btnResizeWindow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
resizeWindow();
}
});
}
return btnResizeWindow;
}
private JButton getBtnRemoveAllButtons() {
if (btnRemoveAllButtons == null) {
btnRemoveAllButtons = new JButton("Remove All Buttons");
btnRemoveAllButtons.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeButtons();
}
});
}
return btnRemoveAllButtons;
}
}
This code is ready to compile with javac or just paste it in your IDE.
Maybe this helps a bit. The Java SE API Documentation is useful too.
I have two Java(.java) files. One has a JButton and JTextField and the other has a Thread. In first Java file, I have added an ActionListener to the JButton so that, when the button is pressed, a thread (object for 2nd .java file in created and thread is initiated) runs which modifies an integer variable continuously. How to display the value of that integer variable (of 2nd .java file) in the JTextField (of 1st .java file) ?
Detection.java
package sample;
public class Detection implements Runnable
{
public String viewers;
public int count;
public void run()
{
try
{
while (true)
{
// i have written code for displaying video.
// and it say how many no. of people in the video
// the no of people is stored in a variable "count"
viewers=""+count; //storing count as string so as to display in the JTextField
}
}
catch (Exception e)
{
System.out.println("Exception: "+e);
}
}
}
UsrInterfac.java
//build using WindowBuilder eclipse juno
package sample;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class UsrInterfac
{
private JFrame frame;
private JTextField textField;
Detection dd = new Detection();
Thread th = new Thread(dd);
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
UsrInterfac window = new UsrInterfac();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public UsrInterfac()
{
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize()
{
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnStartThread = new JButton("Start Thread");
btnStartThread.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
th.start();
}
});
btnStartThread.setBounds(59, 133, 117, 23);
frame.getContentPane().add(btnStartThread);
textField = new JTextField();
textField.setBounds(270, 134, 104, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
}
}
Starting from the basics, while using Swing, it is always best to use LayoutManagers, which can make your work much more easier, in comparison to using Absolute Positioning.
Whenever one needs to change something in the View from some another thread, it is always advisable to do that using EventQueue.invokeLater(...)/EventQueue.invokeAndWait(...).
This small sample program, might be able to help you get an idea, how to accomplish what you so desire :-)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ThreadCounter
{
private CustomThread cThread;
private JTextField tField;
private JButton button;
private int counter;
public ThreadCounter()
{
counter = 0;
}
private void displayGUI()
{
JFrame frame = new JFrame("Thread Counter Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
tField = new JTextField(10);
tField.setText("0");
button = new JButton("Start");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
if (counter == 0)
{
cThread = new CustomThread(tField);
cThread.setFlagValue(true);
cThread.start();
counter = 1;
button.setText("Stop");
}
else
{
try
{
cThread.setFlagValue(false);
cThread.join();
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
counter = 0;
button.setText("Start");
}
}
});
contentPane.add(tField);
contentPane.add(button);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new ThreadCounter().displayGUI();
}
});
}
}
class CustomThread extends Thread
{
private int changingVariable;
private JTextField tField;
private boolean flag = true;
public CustomThread(JTextField tf)
{
changingVariable = 0;
tField = tf;
}
public void setFlagValue(boolean flag)
{
this.flag = flag;
}
#Override
public void run()
{
while (flag)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
tField.setText(
Integer.toString(
++changingVariable));
}
});
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
System.out.println("I am OUT of WHILE");
}
}
Ideally you should post your code. Anyway, when you are calling the thread code, either pass the instance of the first class (object) or an instance of JTextField, so that the thread can set the new value in the text field.