I am trying to add a JTextField at a position where a mouse click happens.The size of the text field should be variable based on the text entered. Below is my code.
public class Paint {
public static void main(String[] args) {
final JFrame frame = new JFrame("Test TextField");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setSize(400, 250);
final JTextField text = new JTextField();
frame.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent me) {
}
});
frame.setVisible(true);
}
}
I want to add the text field at the position where the mouse click happened. The size of the text field should increase based on the text entered in the text field. Can someone let me know how to implement the mouse click method to achieve the same?
I tried to set bounds of the text box using the event x and y positions like
text.setBounds(event.getX(), event.getY(), event.getX(), event.getY());
but with this the size of textField is same as the full frame. but i want a small text box with varying size
First, we need to remove the layout to be able to add component where we want
frame.setLayout(null);
Then, we can check the result of the event with :
frame.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent event) {
System.out.println(event.getX() + " " + event.getY());
}
}
we can notice if we click on the upper left corner that we can't get a (0,0) coordinate. Because A frame is the complete screen, so we need to use the ContentPane or we can simply use a JPanel keep it simple.
final JPanel panel = new JPanel();
panel.setLayout(null);
frame.getContentPane().add(panel);
panel.addMouseListener(new MouseAdapter() {}); //Use the MouseAdapter to not be force to override the full interface of MouseListener.
Now, let's add a component on click. First, we create it during the event (to create a new one each time and we set the size :
final JTextField text = new JTextField();
text.setSize(new Dimension(50, 18)); //I took those randomly...
The important part is the location, set it to the component like :
text.setLocation(event.getX(), event.getY());
And add it to the panel
panel.add(text);
The result is a new JTextField added at the specific position of the click.
Full test code
public static void main(String[] args) {
final JFrame frame = new JFrame("Test TextField");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 250);
final JPanel panel = new JPanel();
panel.setLayout(null);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent event) {
final JTextField text = new JTextField("abc");
text.setLocation(event.getX(), event.getY());
text.setSize(new Dimension(50, 18));
panel.add(text);
}
});
frame.getContentPane().add(panel);
frame.setVisible(true);
}
Note that this is not the best usage a Swing, layouts are there to build efficient screen easily.
Related
Is there a way such that a component that is added to the BorderLayout.PAGE_START area will become scrollable if (and only if) there's not enough space?
I have attached a minimal example. If you resize the complete frame the label in the center will become scrollable, the label at the top won't.
Unfortunately, I can't change the BorderLayout.PAGE_START positioning, as this is given by a framework. However I do have full control over the creation of myComponent.
public static void main(String[] args){
JPanel panel = new JPanel(new BorderLayout());
JComponent myComponent = new JScrollPane(new JLabel("<html>START-START<br><br>START-START</html>"));
panel.add(myComponent, BorderLayout.PAGE_START);
panel.add(new JScrollPane(new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER</html>")), BorderLayout.CENTER);
final JFrame mainframe = new JFrame("Test");
mainframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainframe.getContentPane().add(panel);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);});
}
Is there a way such that a component that is added to the BorderLayout.PAGE_START area will become scrollable if there's not enough space?
Yes there is. Make its preferred height less than its actual height. BorderLayout respects the preferred height of the component contained at PAGE_START, so it doesn't matter how many lines you put in your JLabel, it will be displayed at its preferred height – without scrollbars.
Try the following.
public static void main(String[] args) {
JPanel panel = new JPanel(new BorderLayout());
JComponent myComponent = new JScrollPane(new JLabel("<html>START-START<br><br>START-START</html>"));
myComponent.setPreferredSize(new Dimension(100, 20));
panel.add(myComponent, BorderLayout.PAGE_START);
panel.add(new JScrollPane(new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER</html>")),
BorderLayout.CENTER);
final JFrame mainframe = new JFrame("Test");
mainframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainframe.getContentPane().add(panel);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);
});
}
EDIT
The below code doesn't give the best result but I think it is the way to go. You just need to play around with the different sizes of the different components.
I added a ComponentListener to the content pane of the JFrame. When the JFrame is resized, you need to recalculate the heights of the top component and the center component according to your needs and then update the relevant component sizes. Note that the below code is not a complete solution but hopefully enough to allow you to arrive at a complete solution.
public static void main(String[] args) {
final JFrame mainframe = new JFrame("Test");
JLabel topLabel = new JLabel("<html>START-START<br><br>START-START");
JScrollPane topPane = new JScrollPane(topLabel);
mainframe.add(topPane, BorderLayout.PAGE_START);
JLabel centerLabel = new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER");
centerLabel.setMinimumSize(centerLabel.getPreferredSize());
JPanel centerPane = new JPanel();
centerPane.add(centerLabel);
mainframe.add(centerPane, BorderLayout.CENTER);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);
final Dimension centerPaneDim = centerPane.getPreferredSize();
final Dimension topLabelDim = topLabel.getPreferredSize();
mainframe.getContentPane().addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent e) {
// Do nothing.
}
#Override
public void componentResized(ComponentEvent e) {
Dimension size = e.getComponent().getSize();
if (size.height < centerPaneDim.height + topLabelDim.height + 10) {
topPane.setPreferredSize(new Dimension(topLabelDim.width, 10 + size.height - centerPaneDim.height));
}
else {
topPane.setPreferredSize(new Dimension(topLabelDim.width, topLabelDim.height + 10));
}
e.getComponent().revalidate();
e.getComponent().repaint();
}
#Override
public void componentMoved(ComponentEvent e) {
// Do nothing.
}
#Override
public void componentHidden(ComponentEvent e) {
// Do nothing.
}
});
});
}
This question already has answers here:
Change color of JButton without changing its shape
(2 answers)
Closed 6 years ago.
I want to create a red JButton:
import java.awt.*;
import javax.swing.*;
public class RedButtonTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Red Button Color Test");
JPanel pane1 = new JPanel(new FlowLayout());
JPanel pane2 = new JPanel(new FlowLayout());
JButton button1 = new JButton();
JButton button2 = new JButton();
frame.setSize(new Dimension(300, 300));
button1.setPreferredSize(new Dimension(100, 100));
button2.setPreferredSize(new Dimension(100, 100));
button2.setBackground(Color.red);
button2.setBorderPainted(false); //This line
button2.setOpaque(true);
pane1.add(button1);
pane2.add(button2);
frame.add(pane1, BorderLayout.WEST);
frame.add(pane2, BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Is there a way to make the button red without using
setBorderPainted(false);
When not using it, the borders turn red and not the button itself, however, I do not want to use this line because it removes the soft edges of the button. Is there another way to color a button?
Try using button2.setContentAreaFilled(false);. This will keep the edges but sets the background color. According to the docs:
If true the button will paint the content area. If you wish to have a
transparent button, such as an icon only button, for example, then you
should set this to false. Do not call setOpaque(false). The default
value for the the contentAreaFilled property is true.
I have read many subjects here but I can't make my window with the layout I want.
I simply want all my graphic object to be in a row style like in the first picture here : http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
I've tried GridLayout but it still make my first button giant and then, as I add textfields, it's getting smaller and smaller?!
Here is my code without all the imports:
public class TestScrollPane extends JFrame implements ActionListener{
Dimension dim = new Dimension(200 , 50);
JButton button;
JPanel panel = new JPanel();
JScrollPane scrollpane = new JScrollPane(panel);
public TestScrollPane(){
scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
this.add(scrollpane);
//panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
this.setSize(300, 400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
button = new JButton("click me");
button.setPreferredSize(dim);
panel.add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == button ){
JTextField txt = new JTextField(); // we add a new button
txt.setPreferredSize(dim);
panel.add(txt);
SwingUtilities.updateComponentTreeUI(this); // refresh jframe
}
}
public static void main(String[] args){
TestScrollPane test = new TestScrollPane();
}
}
I just want to have one button per row.
A BoxLayout will respect the minimum/maximum sizes of a component.
For some reason the maximum height of a text field is unlimited so the text field gets all the space available.
So you can do something like:
JTextField txt = new JTextField(10); // we add a new button
//txt.setPreferredSize(dim); // don't hardcode a preferrd size of a component.
txt.setMaximumSize(txt.getPreferredSize());
Also:
//SwingUtilities.updateComponentTreeUI(this); // refresh jframe
Don't use the above method. That is used for a LAF change.
Instead when you add/remove components from a visible GUI you should use:
panel.revalidate();
panel.repaint();
I'm currently following a java tutorial on how to create a guessing game GUI App. At one point in the instructions however, it says to Set the keyboard focus to the field; I don't know what this means or how to do it. Any clarification would be greatly appreciated.
here's the exact instruction: Focus the user's attention on thePlayer field:
Set the keyboard focus to the field.
here's my code so far:
public class GOM extends JFrame implements ActionListener, KeyListener
{
Container content = this.getContentPane();
//top
JTextField theGuess = new JTextField(10);
JLabel bankroll = new JLabel("");
//bottom
JButton newplayer = new JButton("New Player");
JButton newnumber = new JButton("New Number");
JTextField thePlayer = new JTextField(20);
//center
JTextArea theoutput = new JTextArea("");
//invisible
String playerName;
int theNumber;
int numTries;
int numGames;
double amtRemaining;
Random randomizer()
{
Random rnd = new Random();
return rnd;
}
JScrollPane scrollArea = new JScrollPane(theoutput);
public GOM()
{
this.setVisible(true);
this.setSize(500,400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Guess O'Matic");
//top panel
JPanel p1 = new JPanel();
p1.add(theGuess);
p1.add(bankroll);
p1.add(new JLabel("Make Your Guess"));
content.add(p1, BorderLayout.NORTH);
//bottom panel
JPanel p2 = new JPanel();
p2.add(newplayer);
p2.add(newnumber);
p2.add(thePlayer);
content.add(p2, BorderLayout.SOUTH);
// finishing touches
content.add(new JLabel(" "), BorderLayout.WEST);
content.add(new JLabel(" "), BorderLayout.EAST);
content.add(scrollArea, BorderLayout.CENTER);
newplayer.addActionListener(this);
newnumber.addActionListener(this);
thePlayer.addKeyListener(this);
theGuess.addKeyListener(this);
newPlayer();
}
public void newPlayer()
{
theoutput.setText(playerName);
theoutput.setEnabled(false);
theGuess.setEnabled(false);
newnumber.setEnabled(false);
newplayer.setEnabled(false);
theGuess.setBackground(Color.WHITE);
thePlayer.setEnabled(true);
thePlayer.setText(playerName);
thePlayer.setBackground(Color.YELLOW);
}
#Override
public void actionPerformed(ActionEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
#Override
public void keyPressed(KeyEvent e)
{
}
#Override
public void keyReleased(KeyEvent e)
{
}
}
If you have a GUI with several JTextFields and possibly other text components, the keyboard focus can only be on one of those fields at a time. In other words, if you type, only one of the fields can display the caret and then will usually display the typed in text. When a Swing GUI is displayed then the GUI must decide which text component should have focus, and it uses its focus traversal policy to decide this. The default policy usually will put the focus into the first text field created. You can change this by calling requestFocusInWindow() on the text component that you want to hold the focus.
I am developing a Java Application that uses a JTable for capturing user input. The user will have to print data captured in the table. I would want the user to open multiple documents to work on. This I have implemented it this way: I have my JFrame as my main window; on to this JFrame, I have added JTabbedPane so that the user can switch between File, Settings and Tools.Upon clicking new File, the user is taken to a JTabbedPane(place at the center of the JFrame) with a JTable for input. I would want that the next time the user click new File, a new JPanel would be added to the JTabbledPane; but this new JPanel should also contain the JTable for input.This behavior should continue everytime the user creates a new File. This is shown in the images that I have uploaded.(Please forgive for poor drawing).
I have achied this by this code:
public final class QuotPane {
//components to be used
JFrame frame;
JTabbedPane tabbedPane,tablePane;
JPanel quotPane, topPane, pane1, pane2, pane3,tablePanel;
JSeparator sep;
JButton newFile;
QuotPane() {
this.createQuotPane();
this.createGUI();
ButtonActionListener lits= new ButtonActionListener();
newFile.addActionListener(lits);
}
public void createGUI() {
tabbedPane = new JTabbedPane();
tabbedPane.addTab("Create Quot", quotPane);
frame = new JFrame("Qout Interface");
frame.setSize(new Dimension(700, 650));
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
//adding the tabbed pane to the frmae
frame.add(tabbedPane, BorderLayout.NORTH);
}
public void createQuotPane() {
quotPane = new JPanel();
quotPane.setLayout(new BorderLayout());
//creating the top pane
topPane = new JPanel();
topPane.setPreferredSize(new Dimension(650, 145));
topPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.lightGray, Color.lightGray, Color.white, Color.orange));
topPane.setLayout(new MigLayout());
//add the top pane on the quot panel
quotPane.add(topPane, BorderLayout.NORTH);
//adding the panes on the top pane
this.createPanels();
topPane.add(pane1);
topPane.add(pane2);
topPane.add(pane3);
}
//a method to create panes for options
public void createPanels() {
pane1 = new JPanel();
pane1.setPreferredSize(new Dimension(200, 140));
pane1.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
//lets set the icons then
pane1.setLayout(new MigLayout());
Icon fileIcon = new ImageIcon(this.getClass().getResource("/images/fil.jpg"));
newFile = new JButton(fileIcon);
pane1.add(new JLabel("New File"), "wrap");
pane1.add(newFile,"width 20!");
pane2 = new JPanel();
pane2.setPreferredSize(new Dimension(200, 140));
pane2.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
pane3 = new JPanel();
pane3.setPreferredSize(new Dimension(200, 140));
pane3.setMaximumSize(new Dimension(300, 140));
pane3.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.BLUE, Color.lightGray, Color.white, Color.orange));
}
public static void main(String[] args) {
QuotPane qp = new QuotPane();
}
public void createTablePane(){
tablePanel= new JPanel();
}
class ButtonActionListener implements ActionListener{
protected int count=0;
#Override
public void actionPerformed(ActionEvent e) {
if(count==0){
if(e.getSource().equals(QuotPane.this.newFile)){
tablePane=new JTabbedPane();
QuotPane.this.createTablePane();
tablePane.addTab("New Qout", tablePanel);
frame.add(tablePane,BorderLayout.CENTER);
count ++;
}
}else if(count>0)
{
tablePane.add("New Quote",new JPanel());
}}}}
The challenge I am facing here is that I cannot add my JTable to every panel created at run time.I have tried this: tablePane.add("New Quote",myCreatedBeforePanleWithTable) but it is overriding the previous tab.
Here are images of things that I want.I read about JDeskTopPane and JInternalFrame, but can't figure out how to make it work the way I want.
How do I make it work the way I want as shown in the image?
Unfortunately, a Swing Component can only have a single parent. If you add Component A to JPanel X and then to JPanel Y, it will end up in Y.
You will need to have three separate JTables, all sharing a single TableModel. This should be fairly straightforward to implement the basic functionality. It might get tricky if you allow sorting and column reordering and you want that to affect all 3 tables.