Move button on JFrame Java - java

i have a task to make an application wich will do the following:
If I move a mouse the coordinates should be shown on the status bar
If mouse is clicked then the only one button which is on a JPanel should move to coordinates of click
So the problem is that when i do mouse click - it's fine, button moves to coord's of click, but when i start moving mouse the button comes back to the original position
public class Window extends JFrame {
private JLabel statusBar;
private JPanel mainPanel, statusBarPanel;
JButton button;
public Window()
{
super("Window");
setSize(400,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel=new JPanel();
statusBarPanel = new JPanel();
statusBar=new JLabel("Coords: ");
add(statusBarPanel, BorderLayout.SOUTH);
add(mainPanel,BorderLayout.CENTER);
mainPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
statusBarPanel.add(statusBar,BorderLayout.CENTER);
button = new JButton("Default text");
mainPanel.add(button);
MyMouseListener myMouseListener=new MyMouseListener();
mainPanel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
statusBar.setText("Coords: ("+e.getX()+":"+e.getY()+")");
}
});
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
button.setLocation(e.getX()-button.getWidth()/2,e.getY()-button.getHeight()/2);
}
});
mainPanel.setFocusable(true);
setVisible(true);
}
}

This is one of the rare cases where you don't want your panel to have a layout manager, since you need absolute positioning.
JPanel has a default layout manager which is a FlowLayout, and your call to setLocation will only have a temporary effect until the panel revalidates its content and places things where they were supposed to be initially.
See the following example with comments, it should give you the general idea :
public class Window extends JFrame {
private final JLabel statusBar;
private final JPanel mainPanel, statusBarPanel;
JButton button;
public Window() {
super("Window");
setSize(400, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(null);// no layout for absolute positioning
statusBarPanel = new JPanel();
statusBar = new JLabel("Coords: ");
add(statusBarPanel, BorderLayout.SOUTH);
add(mainPanel, BorderLayout.CENTER);
mainPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
statusBarPanel.add(statusBar, BorderLayout.CENTER);
button = new JButton("Default text");
// place the button "manually"
button.setBounds((int) (400 - button.getPreferredSize().getWidth()) / 2, 0,
(int) button.getPreferredSize().getWidth(),
(int) button.getPreferredSize().getHeight());
mainPanel.add(button);
mainPanel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(final MouseEvent e) {
super.mouseMoved(e);
statusBar.setText("Coords: (" + e.getX() + ":" + e.getY() + ")");
}
});
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent e) {
super.mouseClicked(e);
button.setLocation((int) (e.getX() - button.getPreferredSize().getWidth() / 2),
(int) (e.getY() - button.getPreferredSize().getHeight() / 2));
}
});
mainPanel.setFocusable(true);
setVisible(true);
}
}

Related

ImageIcon it is not drawn outside the borders of JFrame

I have a picture that is larger than the screen size, and I want to move the mouse over the image. I wrote the following code
public class Rotation extends JComponent{
int xStart=0;
int yStart=0;
public void rotate(){
JFrame a = new JFrame("example");
ImageIcon imageIcon=new ImageIcon("src/main/resources/img.png");
JLabel label=new JLabel(imageIcon);
a.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
xStart=e.getX()-label.getX();
yStart=e.getY()-label.getY();
}
});
a.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
label.setLocation(e.getX()-xStart, e.getY()-yStart);
}
});
a.add(label);
a.setSize(300,300);
a.setVisible(true);
a.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
Here I'm just moving the image. But it turns out that jlabel does not draw my image outside of the JFrame boundaries
before dragged
after dragged
How can I fix it?
Just to get you going...add the JLabel to a JPanel then size the JLabel to the size of the image. Add the JPanel to the JFrame, for example:
// JFrame:
JFrame frame = new JFrame("example");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(400,400);
// JPanel:
JPanel panel = new JPanel();
//JLabel and Image:
ImageIcon imageIcon = new ImageIcon("src/main/resources/img.png");
JLabel label = new JLabel();
// Set JLabel size to Image Size:
label.setSize(new Dimension(imageIcon.getIconWidth(), imageIcon.getIconHeight()));
// Ensure Horizonal and Vertical alignments in JLabel:
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
label.setIcon(imageIcon);
// Add JLabel to JPanel:
panel.add(label);
// Add JPanel to JFrame:
frame.add(panel);
// Display JFrame with Image:
java.awt.EventQueue.invokeLater(() -> {
frame.setVisible(true);
frame.setLocationRelativeTo(null); // Center form to screen.
});
// Add Mouse Listeners:
frame.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
xStart = e.getX() - label.getX();
yStart = e.getY() - label.getY();
}
});
frame.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
label.setLocation(e.getX() - xStart, e.getY() - yStart);
}
});

In JAVA swing when we implement JAVAFX button using JFXPanel, and then we remove jpanel and add it again then scene is removed or hide

I have demo application in which I am adding JAVAFX button in JPanel using JFXPanel and add scene to JFXPanel. but when I remove and add again JPanel in which my JFXPanel is implemented the scene is removed or hide inside JFXPanel please help.
I have tried to repain() and revalidate() JFXPanel and JPanel also but nothing happens.
Here is the whole code of the application please help.
public class MainForm extends JFrame {
JButton btnTest;
JButton button;
JLabel lblMessage;
JPanel mainPanel;
JFXPanel jfxPanel;
JPanel panel1;
JPanel panel2;
public MainForm() {
initialize();
}
private void initialize() {
setTitle("Touch Screen Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
mainPanel = new JPanel();
mainPanel.setLayout(new MigLayout("insets 10 10 10 10"));
panel1 = new JPanel();
panel1.setLayout(new MigLayout("insets 10 10 10 10"));
panel2 = new JPanel();
panel2.setLayout(new MigLayout("insets 10 10 10 10"));
MouseListener listener = new TestButtonListener();
btnTest = new JButton("Test");
btnTest.addMouseListener(listener);
jfxPanel = new JFXPanel();
jfxPanel.setToolTipText("JFX Panel");
jfxPanel.setScene(createScene());
jfxPanel.setPreferredSize(new Dimension(300, 50));
lblMessage = new JLabel("Your message Here.");
lblMessage.setFont(new Font("Arial", Font.PLAIN, 80));
panel1.add(btnTest, "h 50, w 300, push, c, wrap");
panel1.add(jfxPanel, "h 50, w 300, push, c, wrap");
panel1.add(lblMessage, "pushx, c");
button = new JButton("change");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (button.getText().equals("change")) {
mainPanel.remove(panel1);
mainPanel.repaint();
mainPanel.revalidate();
button.setText("changed");
} else {
mainPanel.add(panel1, "push, grow, wrap, cell 0 0");
mainPanel.repaint();
mainPanel.revalidate();
button.setText("change");
}
}
});
panel2.add(button, "push, align c");
mainPanel.add(panel1, "push, grow, wrap, cell 0 0");
mainPanel.add(panel2, "pushx, growx, cell 0 1");
add(mainPanel);
setVisible(true);
setLocationRelativeTo(null);
}
class TestButtonListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
lblMessage.setText("Button pressed");
}
#Override
public void mouseReleased(MouseEvent arg0) {
lblMessage.setText("Button released");
}
}
public static void main(String[] args) {
new MainForm();
}
#SuppressWarnings("static-access")
private Scene createScene() {
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
Scene scene = new Scene(vBox);
scene.getStylesheets().add(getClass().getResource("res/style.css").toString());
Button button = new Button("JAVAFX Button");
button.setPrefSize(300, 50);
button.setOnTouchPressed(new EventHandler<Event>() {
#Override
public void handle(Event event) {
lblMessage.setText("Button pressed");
}
});
button.setOnTouchReleased(new EventHandler<Event>() {
#Override
public void handle(Event event) {
lblMessage.setText("Button released");
}
});
vBox.getChildren().add(button);
return scene;
}
}
Finally I found the answer of this issue solution is available on this post
Prevent JavaFX thread from dying with JFXPanel Swing interop?

Add jbutton TextArea to the jscrollpane

I want a implementation like this.
JscrollPane's panel is divided into two columns.
First column has jtextarea.
Second column should have a jbutton with Ok text.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestScrollPane extends JFrame {
JPanel newScrollPanel;
JPanel leftPanel;
JScrollPane scrollPane;
JEditorPane editorPane;
JButton button;
public TestScrollPane() {
leftPanel = new JPanel();
newScrollPanel = new JPanel();
editorPane = new JEditorPane();
scrollPane = new JScrollPane(editorPane);
button = new JButton("ok");
leftPanel.setBackground(Color.WHITE);
leftPanel.add(button);
editorPane.setEditable(false);
scrollPane.setPreferredSize(new Dimension(250, 140));
scrollPane.setMinimumSize(new Dimension(10, 10));
String text = "";
for(int i=0;i<50;i++){
text = text + "line " + i + "\n";
}
editorPane.setText(text);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
newScrollPanel.setLayout(new BoxLayout(newScrollPanel, BoxLayout.X_AXIS));
newScrollPanel.add(editorPane);
newScrollPanel.add(leftPanel);
scrollPane.getViewport().add(newScrollPanel);
addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent evt) { }
#Override
public void componentShown(ComponentEvent evt) {
changePane();
}
});
this.add(scrollPane);
setFrame();
}
private void changePane() {
leftPanel.setLayout(null);
Insets insets = leftPanel.getInsets();
Dimension size = button.getPreferredSize();
int buttonY = (int) (insets.top + scrollPane.getHeight() - size.getHeight());
button.setPreferredSize(size);
leftPanel.setPreferredSize(new Dimension(((int) size.getWidth()), editorPane.getHeight()));
button.setBounds(0, buttonY, size.width, size.height);
}
void setFrame(){
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
TestScrollPane testScrollPane = new TestScrollPane();
}
});
}
}
I have two questions.
In my class the ok button is not placed in the correct place. when scroll bar mover is at the top corner , ok button should be in the right bottom corner of the visible area. Ok button should be completely visible. In my code only visible a part of the button. Is there any issue with determining the Y coordinates ?
int buttonY = (int) (insets.top + scrollPane.getHeight() - size.getHeight());
Even though the scroll is moved, ok button should not move with the scroll bar. Is that possible to implement ?

Why JPanel.focusGaind and Lost don't work?

Please take a look at the following code (I've missed the imports purposely)
public class MainFrame extends JFrame {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(10, 11, 414, 240);
contentPane.add(tabbedPane);
JPanel panel = new JPanel();
panel.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent arg0) {
System.out.println("lost");
// I want to do something here, if I reach here!
}
#Override
public void focusGained(FocusEvent arg0) {
System.out.println("gained");
// I want to do something here, if I reach here!
}
});
tabbedPane.addTab("New tab", null, panel, null);
JButton button = new JButton("New button");
panel.add(button);
JPanel panel_1 = new JPanel();
tabbedPane.addTab("New tab", null, panel_1, null);
JPanel panel_2 = new JPanel();
tabbedPane.addTab("New tab", null, panel_2, null);
}
}
I've created this class to test it and then add the onFocusListener in my main code, but it's not working the way I expect. Please tell what's wrong or is this the right EvenetListener at all?
JPanels are not focusable by default. If you ever wanted to use a FocusListener on them, you'd first have to change this property via setFocusable(true).
But even if you do this, a FocusListener is not what you want.
Instead I'd look to listen to the JTabbedPane's model for changes. It uses a SingleSelectionModel, and you can add a ChangeListener to this model, listen for changes, check the component that is currently being displayed and if your component, react.
You are using setBounds and null layouts, something that you will want to avoid doing if you are planning on creating and maintaining anything more than a toy Swing program.
Edit
For example:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.*;
#SuppressWarnings("serial")
public class MainPanel extends JPanel {
private static final int PREF_W = 450;
private static final int PREF_H = 300;
private static final int GAP = 5;
private static final int TAB_COUNT = 5;
private JTabbedPane tabbedPane = new JTabbedPane();
public MainPanel() {
for (int i = 0; i < TAB_COUNT; i++) {
JPanel panel = new JPanel();
panel.add(new JButton("Button " + (i + 1)));
panel.setName("Panel " + (i + 1));
tabbedPane.add(panel.getName(), panel);
}
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
tabbedPane.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent evt) {
Component component = tabbedPane.getSelectedComponent();
System.out.println("Component Selected: " + component.getName());
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("MainPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
JPanel is a lightweight container and it is not a Actionable component so it does not get focus events. It lets you add focus listener because of swing component hierarchy. In Order to get tab selected events you need to use JTabbedPane#addChangeListener.
Hope this helps.

Create blocking glass pane show method

I've created a modal dialog inside a JFrame using the glass pane. My display method is quite simple: it creates a JPanel as glass pane with some alpha background and adds the JLabel and an ok and close button. Then the glass pane is set and displayed via frame.getGlassPane().setVisible(true);.
Everything works fine: if I call the method the pane is displayed and I can click ok or cancel and the glass pane hides. But the method returns directly after showing the glass pane. But I want it to behave like the JOptionPane methods: they block until the dialog is closed.
But everytime I'm trying to insert any kind of busy waiting at the end of my show method the GUI is frozen if I click the open button. I've also tried to get the mechanism from JDialog#show() but that's a bit to complicated for me.
So how to block the show method while the glass pane is visible?
Here is a simple example:
public class GlassPaneSSCE extends JPanel {
private JFrame parentFrame;
public GlassPaneSSCE(JFrame parent) {
parentFrame = parent;
addKeyListener(new KeyAdapter() {});
addMouseListener(new MouseAdapter() {});
setBackground(new Color(0, 0, 0, 100));
initGui();
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
private void initGui() {
setLayout(new FlowLayout(FlowLayout.CENTER));
setOpaque(false);
final JPanel content = new JPanel(new BorderLayout(4, 4));
content.setOpaque(true);
content.setBorder(new EmptyBorder(8, 8, 8, 8));
JLabel top = new JLabel("Title of this little modal dialog");
content.add(top, BorderLayout.NORTH);
JPanel inner = new JPanel(new BorderLayout());
content.add(inner, BorderLayout.CENTER);
inner.add(new JScrollPane(new JList(new String[] {
"Item 1 ",
"Item 2", "Item 3"
})));
Box ctrlButtons = Box.createHorizontalBox();
ctrlButtons.setBorder(new EmptyBorder(0, 4, 4, 4));
ctrlButtons.add(Box.createHorizontalGlue());
ctrlButtons.add(new JButton(new AbstractAction("OK") {
#Override
public void actionPerformed(ActionEvent e) {
parentFrame.getGlassPane().setVisible(false);
parentFrame.setGlassPane(new JPanel());
}
}));
content.add(ctrlButtons, BorderLayout.SOUTH);
add(content);
}
public void display() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
parentFrame.setGlassPane(GlassPaneSSCE.this);
parentFrame.getGlassPane().setVisible(true);
// Set the focus on the glass pane
requestFocus();
setFocusCycleRoot(true);
}
});
// The next line should be executed only if
// the ok button is clicked and not before
System.out.println("End of display()");
}
public static void main(String[] args) {
final JFrame f = new JFrame();
f.setLayout(new FlowLayout(FlowLayout.CENTER));
JTextArea tp = new JTextArea(10, 10);
for (int i = 0; i < 20; i++) {
JButton b = new JButton("Open");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
GlassPaneSSCE gp = new GlassPaneSSCE(f);
gp.display();
}
});
f.add(b);
tp.append("Item " + (i+1) + "\n");
}
f.add(new JScrollPane(tp));
f.setSize(600, 600);
f.setVisible(true);
}
}

Categories