After researching how to use Label DnD I come across with using this solution:
public class LayerItem extends JLabel {
int x = 0, y = 0;
public LayerItem(String text) {
this.setText(text);
this.addMouseMotionListener(new MouseAdapter(){
#Override
public void mouseDragged(MouseEvent evt){
lblMouseDragged(evt);
}
});
}
protected void lblMouseDragged(MouseEvent evt){
this.x = evt.getX();
this.y = evt.getY();
}
}
As the user clicks, and holds, the JLabel the X and Y are recorded as the mouse moves. However, I am stuck on how to know when the click is stopped (ie, user reaches his targeted JPanel) to then move the text into it.
The only bit of reference to allowing JPanels to receive a drop action is by doing something like this:
new JPanel().setDropTarget(getDropTarget());
However, I cannot again find any references on passing through the JLabel as the drop target with the Coords (Absolute layout).
After looking at a few examples posted by #MadProgrammer I came up with a solution that extends both the JPanel and JLabel. Here is the JLabel class:
public class LayerItem extends JLabel {
public LayerItem(String text) {
this.setText(text);
this.setTransferHandler(new ValueExportTransferHandler(text));
this.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
JLabel lbl = (JLabel) e.getSource();
TransferHandler handle = lbl.getTransferHandler();
handle.exportAsDrag(lbl, e, TransferHandler.COPY);
}
});
}
protected static class ValueExportTransferHandler extends TransferHandler {
public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor;
private String value;
public ValueExportTransferHandler(String value) {
this.value = value;
}
public String getValue() {
return value;
}
#Override
public int getSourceActions(JComponent c) {
return DnDConstants.ACTION_COPY_OR_MOVE;
}
#Override
protected Transferable createTransferable(JComponent c) {
Transferable t = new StringSelection(getValue());
return t;
}
#Override
protected void exportDone(JComponent source, Transferable data, int action) {
super.exportDone(source, data, action);
// Clean up and remove the LayerItem that was moved
((LayerItem) source).setVisible(false);
((LayerItem) source).getParent().remove((LayerItem) source);
}
}
}
Here is the class for the JPanel:
public class LayerContainer extends JPanel {
public LayerContainer() {
this.setTransferHandler(new ValueImportTransferHandler());
this.setLayout(new GridBagLayout()); // Optional layout
this.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY), new EmptyBorder(20, 20, 20, 20))); // Optional border
}
protected static class ValueImportTransferHandler extends TransferHandler {
public static final DataFlavor SUPPORTED_DATE_FLAVOR = DataFlavor.stringFlavor;
public ValueImportTransferHandler() {
}
#Override
public boolean canImport(TransferHandler.TransferSupport support) {
return support.isDataFlavorSupported(SUPPORTED_DATE_FLAVOR);
}
#Override
public boolean importData(TransferHandler.TransferSupport support) {
boolean accept = false;
if (canImport(support)) {
try {
Transferable t = support.getTransferable();
Object value = t.getTransferData(SUPPORTED_DATE_FLAVOR);
if (value instanceof String) { // Ensure no errors
// TODO: here you can create your own handler
// ie: ((LayerContainer) component).getHandler()....
Component component = support.getComponent();
LayerItem j = new LayerItem((String) value);
((LayerContainer) component).add(j); // Add a new drag JLabel
accept = true;
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
return accept;
}
}
}
Here is an example of how you could use this (drag from one JPanel to another and back again):
JPanel left_panel = new LayerContainer();
panel_1.setBounds(28, 47, 129, 97);
add(panel_1);
LayerContainer right_panel = new LayerContainer();
layerContainer.setBounds(203, 47, 129, 97);
add(layerContainer);
JLabel lblToDrag = new LayerItem("Drag Me");
GridBagConstraints gbc_lblToDrag = new GridBagConstraints();
gbc_lblDragMe.gridx = 0;
gbc_lblDragMe.gridy = 0;
panel_right.add(lblToDrag, gbc_lblToDrag);
For future use, I'll create a onTransfer() method and create my own LayerContainerHandler() which overrites a run() method so each time a Label is moved to different Containers, it execute seperate actions.
Related
I'm new to Java and struggling to get a label displayed in the frame before the list is displayed this snippet ? Thank you very much! I tried having the JLable in the TopFiveDestinationList class main method but it overrides the list.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TopFiveDestinationList {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TopDestinationListFrame topDestinationListFrame = new TopDestinationListFrame();
//JLabel nameLabel = new JLabel("Developer: John Smith");
// JFrame frame1 = new JFrame("FrameDemo");
// JLabel nameLabel = new JLabel("Developer: John Smith");
// topDestinationListFrame.add(nameLabel);
topDestinationListFrame.setTitle("111111111Top 5 Destination List");
topDestinationListFrame.setVisible(true);
}
});
}
}
class TopDestinationListFrame extends JFrame {
private DefaultListModel listModel;
public TopDestinationListFrame() {
super("Top Five Destination List");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(900, 750);
listModel = new DefaultListModel();
//Make updates to your top 5 list below. Import the new image files to resources directory.
addDestinationNameAndPicture("1. New York City (short sentence description)", new ImageIcon(getClass().getResource("/resources/NewYorkCity.jpg")));
addDestinationNameAndPicture("2. San Francisco", new ImageIcon(getClass().getResource("/resources/SanFrancisco.jpg")));
addDestinationNameAndPicture("3. Grand Canyon", new ImageIcon(getClass().getResource("/resources/GrandCanyon.jpg")));
addDestinationNameAndPicture("4. Yosemite Valley", new ImageIcon(getClass().getResource("/resources/YosemiteValley.jpg")));
addDestinationNameAndPicture("5. Las Vegas", new ImageIcon(getClass().getResource("/resources/LasVegas.jpg")));
JList list = new JList(listModel);
JScrollPane scrollPane = new JScrollPane(list);
list.setBackground(Color.DARK_GRAY);
list.setSelectionBackground(Color.CYAN);
TextAndIconListCellRenderer renderer = new TextAndIconListCellRenderer(2);
list.setCellRenderer(renderer);
// getContentPane().add(nameLabel);
getContentPane().add(scrollPane, BorderLayout.CENTER);
}
private void addDestinationNameAndPicture(String text, Icon icon) {
TextAndIcon tai = new TextAndIcon(text, icon);
listModel.addElement(tai);
}
}
class TextAndIcon {
private String text;
private Icon icon;
public TextAndIcon(String text, Icon icon) {
this.text = text;
this.icon = icon;
}
public String getText() {
return text;
}
public Icon getIcon() {
return icon;
}
public void setText(String text) {
this.text = text;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
}
class TextAndIconListCellRenderer extends JLabel implements ListCellRenderer {
private static final Border NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
private Border insideBorder;
public TextAndIconListCellRenderer() {
this(0, 0, 0, 0);
}
public TextAndIconListCellRenderer(int padding) {
this(padding, padding, padding, padding);
}
public TextAndIconListCellRenderer(int topPadding, int rightPadding, int bottomPadding, int leftPadding) {
insideBorder = BorderFactory.createEmptyBorder(topPadding, leftPadding, bottomPadding, rightPadding);
setOpaque(true);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean hasFocus) {
// The object from the combo box model MUST be a TextAndIcon.
TextAndIcon tai = (TextAndIcon) value;
// Sets text and icon on 'this' JLabel.
setText(tai.getText());
setIcon(tai.getIcon());
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
Border outsideBorder;
if (hasFocus) {
outsideBorder = UIManager.getBorder("List.focusCellHighlightBorder");
} else {
outsideBorder = NO_FOCUS_BORDER;
}
setBorder(BorderFactory.createCompoundBorder(outsideBorder, insideBorder));
setComponentOrientation(list.getComponentOrientation());
setEnabled(list.isEnabled());
setFont(list.getFont());
return this;
}
// The following methods are overridden to be empty for performance
// reasons. If you want to understand better why, please read:
//
// http://java.sun.com/javase/6/docs/api/javax/swing/DefaultListCellRenderer.html#override
public void validate() {}
public void invalidate() {}
public void repaint() {}
public void revalidate() {}
public void repaint(long tm, int x, int y, int width, int height) {}
public void repaint(Rectangle r) {}
}
I tried creating a JLabel in TopFiveDestinationList frame but it overrides the list
On the MVC pattern, which is the best option for the Model to notify the View (if this is the right approach in the first place) where, from all the fields of data the Model is storing, only a couple of them are updated. Specifically when we only want to update specific fields of the View.
I am currently using a MVC pattern with Observer/Subscriber (JAVA Swing) as described here: https://stackoverflow.com/a/6963529 but when the Model updates, it changes everything in the View when the update() funcion is called, it's impossible to determine which field from the Model changed in order to update only the required field in the View.
I read this topic: https://softwareengineering.stackexchange.com/a/359008 and this as well: https://stackoverflow.com/a/9815189 which I think it's usefull, but for the later, I can't understand very well how can I set a propertyChangeListener on a variale (int, float, etc). Also related to this: https://stackoverflow.com/a/9815189
The Main class where the software start to run:
public class Main {
public static void main(String[] args) {
Model m = new Model();
View v = new View(m);
Controller c = new Controller(m, v);
c.initController();
}
}
So the code that I have on Model is this:
public class Model extends Observable {
//...
private float speed;
private int batteryPercentage;
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
setChanged();
notifyObservers();
}
public int getBatteryPercentage() {
return batteryPercentage;
}
public void setBatteryPercentage(int batteryPercentage) {
this.batteryPercentage = batteryPercentage;
setChanged();
notifyObservers();
}
}
The view knows the Model:
public class View implements Observer {
private Model model;
private JTextField txtFldSpeed;
private JTextField txtFldBattery;
private JFrame mainWindow;
public View(Model m) {
this.model = m;
initialize();
}
private void initialize() {
mainWindow = new JFrame();
mainWindow.setTitle("New Window");
mainWindow.setMinimumSize(new Dimension(1280, 720));
mainWindow.setBounds(100, 100, 1280, 720);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel tPanel1 = new JPanel();
tPanel1.setBorder(new LineBorder(new Color(0, 0, 0)));
tPanel1.setLayout(null);
mainWindow.getContentPane().add(tPanel1);
mainWindow.getContentPane().add(tPanel1);
txtFldSpeed = new JTextField();
txtFldSpeed.setEditable(false);
txtFldSpeed.setBounds(182, 11, 116, 22);
tPanel1.add(txtFldSpeed);
txtFldBattery = new JTextField();
txtFldBattery.setEditable(false);
txtFldBattery.setBounds(182, 43, 116, 22);
tPanel1.add(txtFldBattery);
mainWindow.setVisible(true);
}
#Override
public void update(Observable o, Object arg) {
txtFldSpeed.setText(Float.toString(model.getSpeed()) + " kn");
txtFldBattery.setText(Integer.toString(model.getBatteryPercentage()) + " %");
}
}
The Controller adds the View as a Observer of the Model:
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v) {
this.model = m;
this.view = v;
}
public void initController() {
model.addObserver(view);
model.setSpeed(10);
}
}
What I am expecting is something that, when the Model is updated, let's say, function setSpeed() is called, the View is told that she needs to update itself on that specific field and not every "changable" field (like the txtFldBattery.
I want to do this because on the View, there are fields being updated a couple of times per second, and because I need to update everything on the view, a JComboBox which doesn't need to update that often, keeps closing when trying to select a option.
I would use SwingPropertyChangeSupport, make each of the model's state fields a "bound property" so that each state field can be listened to separately.
For instance, say you have a model that looked like this:
public class MvcModel {
public static final String SPEED = "speed";
public static final String BATTERY = "battery";
public static final int MAX_SPEED = 40;
private float speed;
private int batteryPercentage;
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
float oldValue = this.speed;
float newValue = speed;
this.speed = speed;
pcSupport.firePropertyChange(SPEED, oldValue, newValue);
}
public int getBatteryPercentage() {
return batteryPercentage;
}
public void setBatteryPercentage(int batteryPercentage) {
int oldValue = this.batteryPercentage;
int newValue = batteryPercentage;
this.batteryPercentage = batteryPercentage;
pcSupport.firePropertyChange(BATTERY, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}
Both the speed and the batteryPercent fields are "bound fields" in that any changes to these fields will trigger the property change support object to fire a notification message to any listeners that have registered with the support object, as reflected in the public void setXxxx(...) methods.
This way the controller could register listeners on the model for whatever properties it wants to listen to, and then notify the view of any changes. For example:
class SpeedListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
float speed = model.getSpeed();
view.setSpeed(speed);
}
}
The set up could look something like:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class MVC2 {
private static void createAndShowGui() {
MvcModel model = new MvcModel();
MvcView view = new MvcView();
MvcController controller = new MvcController(model, view);
controller.init();
JFrame frame = new JFrame("MVC2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(view.getMainDisplay());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MvcView {
private JPanel mainPanel = new JPanel();
private JSlider speedSlider = new JSlider(0, MvcModel.MAX_SPEED);
private JSlider batterySlider = new JSlider(0, 100);
private JProgressBar speedBar = new JProgressBar(0, MvcModel.MAX_SPEED);
private JProgressBar batteryPercentBar = new JProgressBar(0, 100);
public MvcView() {
speedSlider.setMajorTickSpacing(5);
speedSlider.setMinorTickSpacing(1);
speedSlider.setPaintTicks(true);
speedSlider.setPaintLabels(true);
speedSlider.setPaintTrack(true);
batterySlider.setMajorTickSpacing(20);
batterySlider.setMinorTickSpacing(5);
batterySlider.setPaintTicks(true);
batterySlider.setPaintLabels(true);
batterySlider.setPaintTrack(true);
speedBar.setStringPainted(true);
batteryPercentBar.setStringPainted(true);
JPanel inputPanel = new JPanel(new GridLayout(0, 1));
inputPanel.add(createTitledPanel("Speed", speedSlider));
inputPanel.add(createTitledPanel("Battery %", batterySlider));
JPanel displayPanel = new JPanel(new GridLayout(0, 1));
displayPanel.add(createTitledPanel("Speed", speedBar));
displayPanel.add(createTitledPanel("Battery %", batteryPercentBar));
mainPanel.setLayout(new GridLayout(1, 0));
mainPanel.add(createTitledPanel("Input", inputPanel));
mainPanel.add(createTitledPanel("Display", displayPanel));
}
private JComponent createTitledPanel(String title, JComponent component) {
JPanel titledPanel = new JPanel(new BorderLayout());
titledPanel.setBorder(BorderFactory.createTitledBorder(title));
titledPanel.add(component);
return titledPanel;
}
public JComponent getMainDisplay() {
return mainPanel;
}
public void setSpeed(float speed) {
speedBar.setValue((int) speed);
}
public void setBatteryPercent(int batteryPercent) {
batteryPercentBar.setValue(batteryPercent);
}
public JSlider getSpeedSlider() {
return speedSlider;
}
public JSlider getBatterySlider() {
return batterySlider;
}
}
class MvcController {
private MvcModel model;
private MvcView view;
public MvcController(MvcModel model, MvcView view) {
this.model = model;
this.view = view;
model.addPropertyChangeListener(MvcModel.BATTERY, new BatteryListener());
model.addPropertyChangeListener(MvcModel.SPEED, new SpeedListener());
view.getSpeedSlider().addChangeListener(chngEvent -> {
int value = view.getSpeedSlider().getValue();
model.setSpeed(value);
});
view.getBatterySlider().addChangeListener(chngEvent -> {
int value = view.getBatterySlider().getValue();
model.setBatteryPercentage(value);
});
}
public void init() {
view.getSpeedSlider().setValue(10);
view.getBatterySlider().setValue(100);
model.setSpeed(10);
model.setBatteryPercentage(100);
}
class SpeedListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
float speed = model.getSpeed();
view.setSpeed(speed);
}
}
class BatteryListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
int batteryPercent = model.getBatteryPercentage();
view.setBatteryPercent(batteryPercent);
}
}
}
Side note: Observer and Observable have been deprecated in the most recent version of Java and so should their use should probably be avoided.
In your update method implementation you can determine with first argument o which Observable has changed and with second argument arg which value changed when you call: notifyObservers(this.speed);
Note that notifyObservers's signature accepts Object, and float primitive is not a subclass of Object.
i am doing one project related to swings in this i am facing one problem like some 5 check boxes are there in this if i delete two non immediate check boxes (or) single check box i am able to delete but if i delete two immediate check boxes i am not able to delete i.e i have check boxes like 1,2,3,4,5 if i delete 1 and 3 , 1 and 4 , or 3 and 5 etc... (or) 1,2,3 etc.. if i delete using this combination i am able to delete but if i delete 1 and 2 or 2 and 3 or
4 and 5 like immediate check boxes i am not able to delete i am new to swings i don't no what's happening wrong and where. when i am searching for the answer i found this link
Deleting check boxes
The same program i am using the different approach, Here i am creating my own custom classes here my program:
import java.awt.*;
import java.util.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ListModels extends JDialog {
#SuppressWarnings("rawtypes")
private JList list;
private JPanel rightPanel;
JButton cancel = new JButton("Cancel");
JButton delbtn = new JButton("Delete");
public ListModels() {
createList();
createButtons();
initUI();
}
public ListModels(List<String> values) {
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private void createList() {
myModel mModel = new myModel(new CheckListItem[] {
new CheckListItem("78"), new CheckListItem("79"),
new CheckListItem("80"), new CheckListItem("81"),
new CheckListItem("82") });
list = new JList(mModel);
list.setCellRenderer(new CheckListRenderer());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent event) {
JList list = (JList) event.getSource();
// Get index of item clicked
int index = list.locationToIndex(event.getPoint());
CheckListItem item = (CheckListItem) list.getModel()
.getElementAt(index);
if (item.isSelected) {
System.out.println("i am selected ");
}
// Toggle selected state
item.setSelected(!item.isSelected());
// Repaint cell
list.repaint(list.getCellBounds(index, index));
}
});
}
private void createButtons() {
rightPanel = new JPanel();
// JButton cancel = new JButton("Cancel");
cancel.setMaximumSize(cancel.getMaximumSize());
// JButton delbtn = new JButton("Delete");
delbtn.setMaximumSize(cancel.getMaximumSize());
// Cancel button
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
// Cancel
delbtn.addActionListener(new ActionListener() {
#SuppressWarnings("rawtypes")
public void actionPerformed(ActionEvent event) {
// CheckListItem item = (CheckListItem)
// list.getModel().getElementAt(index);
int dialogButton = JOptionPane.YES_NO_OPTION;
int dialogResult = JOptionPane.showConfirmDialog(null,
"Are you sure you want to delete the selected map",
"Delete", dialogButton);
myModel mModel = (myModel) list.getModel();
ListModel currentModel = list.getModel();
for (int i = 0; i < mModel.getSize(); i++) {
CheckListItem item = (CheckListItem) mModel.getElementAt(i);
if(!item.isSelected)
{
System.out.println("i am in not selected item "+item);
}
else if (item.isSelected()) {
System.out.println("i am selected item "+item);
if (dialogResult == JOptionPane.YES_OPTION) {
// Location loc=(Location) mModel.getElementAt(i);
mModel.removeAt(i);
mModel.fireIntervalRemoved(this, i,mModel.getSize());
}
}
}
}
});
// JPanel buttonPane = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.LINE_AXIS));
rightPanel.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));
rightPanel.add(Box.createHorizontalStrut(60));
rightPanel.add(delbtn);
rightPanel.add(Box.createRigidArea(new Dimension(10, 0)));
rightPanel.add(cancel);
}
private void initUI() {
// JScroll Panel
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
listScroller.setAlignmentX(LEFT_ALIGNMENT);
// Lay out the label and scroll pane from top to bottom.
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
// Add all to the panel
listPane.add(Box.createRigidArea(new Dimension(0, 5)));
listPane.add(listScroller);
listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// Lay out the buttons from left to right.
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalStrut(60));
buttonPane.add(delbtn);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(cancel);
listPane.add(buttonPane);
// Put everything together, using the content pane's BorderLayout.
Container contentPane = getContentPane();
contentPane.add(listPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.PAGE_END);
add(listPane);
add(listPane);
setTitle("Delete Map");
setSize(300, 250);
setLocationRelativeTo(null);
}
class CheckListItem {
private String label;
private boolean isSelected = false;
public CheckListItem(String label) {
this.label = label;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
public String toString() {
return label;
}
}
#SuppressWarnings({ "rawtypes" })
class CheckListRenderer extends JCheckBox implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean hasFocus) {
setEnabled(list.isEnabled());
setSelected(((CheckListItem) value).isSelected());
setFont(list.getFont());
setBackground(list.getBackground());
setForeground(list.getForeground());
setText(value.toString());
return this;
}
}
class myModel extends AbstractListModel<CheckListItem> {
private List<CheckListItem> items;
public myModel(CheckListItem[] items) {
super();
this.items = new ArrayList<ListModels.CheckListItem>();
for (CheckListItem item : items) {
this.items.add(item);
}
}
/*
* #Override protected void fireContentsChanged(Object Source, int
* index0, int index1) { super.fireContentsChanged(Source, index0,
* index1); }
*/
#Override
public CheckListItem getElementAt(int index) {
return items.get(index);
}
#Override
protected void fireIntervalRemoved(Object Source, int index0, int index1) {
// TODO Auto-generated method stub
super.fireIntervalRemoved(Source, index0, index1);
}
#Override
public int getSize() {
return items.size();
}
public void removeAt(int item) {
items.remove(item);
}
public void addAt(int index, CheckListItem item) {
items.set(index, item);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
List<String> values = new ArrayList<String>();
values.addAll(newList);
ListModels ex = new ListModels();
ex.setVisible(true);
}
});
}
}
Finally in this program i am loading the check boxes through my custom class directly giving numbers ,I want to call this class from my main method and pass the numbers through Array list or array. Any HELP IS WELCOME and THANKS.
for (int i = 0; i < mModel.getSize(); i++)
You need to start at the end of the list and work backwards:
for (int i = mModel.getSize() - 1; i >=0; i--)
because if you start at 0, all the rows will shift down by one when the row is removed.
So I have a label and I want to do the next, as default it starts on red background color, when i do first click (mousePressed) i change the background color to Green.
Now, i want it to turn back to Red once i press for 2nd time once i press it again.
Something like if it is red, turn green.
And if it is green, turn red.
However i don't manage to get it right... I tried something like this:
Object o = evt.getSource();
boolean checkGreen = false;
if (o.equals(lblSI)) {
lblSI.setBackground(Color.GREEN);
checkGreen = true;
}
if (o.equals(lblSI) && checkGreen == true) {
lblSI.setBackground(Color.RED);
}
But it obviously doesnt work since I first turn it green, then red, its an instant change, cant find the right code...
You can use an else to take a different action. However, the state of the green color needs to be part of the object fields, not defined in the action method (as it would be reset to false for each action then).
It might also be more clear if you separate the check for the source and the check for color selection.
... object definition ...
boolean isGreen = false;
... action listener...
Object o = evt.getSource();
if (o.equals(lblSI)) {
if (isGreen) {
lblSI.setBackground(Color.RED);
} else {
lblSI.setBackground(Color.GREEN);
}
isGreen = !isGreen;
}
Adding a complete example that instead sets the foreground color as background color will not work on all platforms.
public class RedGreen implements Runnable {
private JButton press;
#Override
public void run() {
JFrame frame = new JFrame("RedGreen");
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
press = new JButton("Press");
press.addActionListener(new ActionListener() {
boolean isGreen = false;
#Override
public void actionPerformed(ActionEvent e) {
if (isGreen) {
press.setForeground(Color.RED);
} else {
press.setForeground(Color.GREEN);
}
isGreen = !isGreen;
}
});
frame.getContentPane().add(press);
frame.pack();
frame.setVisible(true);
}
public static void main(String...args) throws Exception {
SwingUtilities.invokeAndWait(new RedGreen());
}
}
Here we go for a pretty clean way of doing it. I hope this answers your question.
public class MyLabel extends JLabel implements MouseListener {
private boolean isRed;
private boolean isGreen;
private boolean first_time = true;
public MyLabel(String name) {
super(name);
this.isRed = true;
this.isGreen = false;
this.setOpaque(true);
this.addMouseListener(this);
this.setBackground(Color.red);
}
public void setRed(boolean val) {
isRed = val;
}
public void setGreen(boolean val) {
isGreen = val;
}
public boolean getRed() {
return isRed;
}
public boolean getGreen() {
return isGreen;
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
if (first_time) {
first_time = false;
this.setGreen(true);
this.setRed(false);
}
if (getRed()) {
this.setBackground(Color.red);
this.setGreen(true);
this.setRed(false);
}
else if (getGreen()) {
this.setBackground(Color.green);
this.setGreen(false);
this.setRed(true);
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
And the next:
public class TestFrame extends JFrame {
public TestFrame() {
JLabel label = new MyLabel("Name of Label");
this.add(label);
this.setVisible(true);
pack();
}
}
And lastly the main method:
public class Main {
public static void main(String[] args) {
new TestFrame();
}
}
If you have any questions about what I'm doing feel free to ask me. This is how I learnt myself how to code better by asking questions. All the best with the coding :)
I would like to add a hint value to my javax.swing.JTextField. It should look like Firefox rendering of <input type="text" title="bla">. This creates an edit field with the text 'bla' in the background. If the textbox has focus the title-text disappears and just reappears if the user leaves the editbox without text.
Is there a (free) swing component that does something like this?
You could create your own:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
final JTextField textFieldA = new HintTextField("A hint here");
final JTextField textFieldB = new HintTextField("Another hint here");
frame.add(textFieldA, BorderLayout.NORTH);
frame.add(textFieldB, BorderLayout.CENTER);
JButton btnGetText = new JButton("Get text");
btnGetText.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String message = String.format("textFieldA='%s', textFieldB='%s'",
textFieldA.getText(), textFieldB.getText());
JOptionPane.showMessageDialog(frame, message);
}
});
frame.add(btnGetText, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}
class HintTextField extends JTextField implements FocusListener {
private final String hint;
private boolean showingHint;
public HintTextField(final String hint) {
super(hint);
this.hint = hint;
this.showingHint = true;
super.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
if(this.getText().isEmpty()) {
super.setText("");
showingHint = false;
}
}
#Override
public void focusLost(FocusEvent e) {
if(this.getText().isEmpty()) {
super.setText(hint);
showingHint = true;
}
}
#Override
public String getText() {
return showingHint ? "" : super.getText();
}
}
If you're still on Java 1.5, replace the this.getText().isEmpty() with this.getText().length() == 0.
Here is a simple way that looks good in any L&F:
public class HintTextField extends JTextField {
public HintTextField(String hint) {
_hint = hint;
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (getText().length() == 0) {
int h = getHeight();
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Insets ins = getInsets();
FontMetrics fm = g.getFontMetrics();
int c0 = getBackground().getRGB();
int c1 = getForeground().getRGB();
int m = 0xfefefefe;
int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1);
g.setColor(new Color(c2, true));
g.drawString(_hint, ins.left, h / 2 + fm.getAscent() / 2 - 2);
}
}
private final String _hint;
}
Here is a single class copy/paste solution:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.plaf.basic.BasicTextFieldUI;
import javax.swing.text.JTextComponent;
public class HintTextFieldUI extends BasicTextFieldUI implements FocusListener {
private String hint;
private boolean hideOnFocus;
private Color color;
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
repaint();
}
private void repaint() {
if(getComponent() != null) {
getComponent().repaint();
}
}
public boolean isHideOnFocus() {
return hideOnFocus;
}
public void setHideOnFocus(boolean hideOnFocus) {
this.hideOnFocus = hideOnFocus;
repaint();
}
public String getHint() {
return hint;
}
public void setHint(String hint) {
this.hint = hint;
repaint();
}
public HintTextFieldUI(String hint) {
this(hint,false);
}
public HintTextFieldUI(String hint, boolean hideOnFocus) {
this(hint,hideOnFocus, null);
}
public HintTextFieldUI(String hint, boolean hideOnFocus, Color color) {
this.hint = hint;
this.hideOnFocus = hideOnFocus;
this.color = color;
}
#Override
protected void paintSafely(Graphics g) {
super.paintSafely(g);
JTextComponent comp = getComponent();
if(hint!=null && comp.getText().length() == 0 && (!(hideOnFocus && comp.hasFocus()))){
if(color != null) {
g.setColor(color);
} else {
g.setColor(comp.getForeground().brighter().brighter().brighter());
}
int padding = (comp.getHeight() - comp.getFont().getSize())/2;
g.drawString(hint, 2, comp.getHeight()-padding-1);
}
}
#Override
public void focusGained(FocusEvent e) {
if(hideOnFocus) repaint();
}
#Override
public void focusLost(FocusEvent e) {
if(hideOnFocus) repaint();
}
#Override
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener(this);
}
#Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener(this);
}
}
Use it like this:
TextField field = new JTextField();
field.setUI(new HintTextFieldUI("Search", true));
Note that it is happening in protected void paintSafely(Graphics g).
Take a look at this one: http://code.google.com/p/xswingx/
It is not very difficult to implement it by yourself, btw. A couple of listeners and custom renderer and voila.
For any Swing component (that is, anything that extends JComponent), you can call the setToolTipText(String) method.
For more information, reference the following links:
API Documentation for setToolTipText
"How to Use Tool Tips" tutorial
Have look at WebLookAndFeel at https://github.com/mgarin/weblaf/
WebTextField txtName = new com.alee.laf.text.WebTextField();
txtName.setHideInputPromptOnFocus(false);
txtName.setInputPrompt("Name");
txtName.setInputPromptFont(new java.awt.Font("Ubuntu", 0, 18));
txtName.setInputPromptForeground(new java.awt.Color(102, 102, 102));
txtName.setInputPromptPosition(0);
If you still look for a solution, here's one that combined other answers (Bart Kiers and culmat) for your reference:
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
public class HintTextField extends JTextField implements FocusListener
{
private String hint;
public HintTextField ()
{
this("");
}
public HintTextField(final String hint)
{
setHint(hint);
super.addFocusListener(this);
}
public void setHint(String hint)
{
this.hint = hint;
setUI(new HintTextFieldUI(hint, true));
//setText(this.hint);
}
public void focusGained(FocusEvent e)
{
if(this.getText().length() == 0)
{
super.setText("");
}
}
public void focusLost(FocusEvent e)
{
if(this.getText().length() == 0)
{
setHint(hint);
}
}
public String getText()
{
String typed = super.getText();
return typed.equals(hint)?"":typed;
}
}
class HintTextFieldUI extends javax.swing.plaf.basic.BasicTextFieldUI implements FocusListener
{
private String hint;
private boolean hideOnFocus;
private Color color;
public Color getColor()
{
return color;
}
public void setColor(Color color)
{
this.color = color;
repaint();
}
private void repaint()
{
if(getComponent() != null)
{
getComponent().repaint();
}
}
public boolean isHideOnFocus()
{
return hideOnFocus;
}
public void setHideOnFocus(boolean hideOnFocus)
{
this.hideOnFocus = hideOnFocus;
repaint();
}
public String getHint()
{
return hint;
}
public void setHint(String hint)
{
this.hint = hint;
repaint();
}
public HintTextFieldUI(String hint)
{
this(hint, false);
}
public HintTextFieldUI(String hint, boolean hideOnFocus)
{
this(hint, hideOnFocus, null);
}
public HintTextFieldUI(String hint, boolean hideOnFocus, Color color)
{
this.hint = hint;
this.hideOnFocus = hideOnFocus;
this.color = color;
}
protected void paintSafely(Graphics g)
{
super.paintSafely(g);
JTextComponent comp = getComponent();
if(hint != null && comp.getText().length() == 0 && (!(hideOnFocus && comp.hasFocus())))
{
if(color != null)
{
g.setColor(color);
}
else
{
g.setColor(Color.gray);
}
int padding = (comp.getHeight() - comp.getFont().getSize()) / 2;
g.drawString(hint, 5, comp.getHeight() - padding - 1);
}
}
public void focusGained(FocusEvent e)
{
if(hideOnFocus) repaint();
}
public void focusLost(FocusEvent e)
{
if(hideOnFocus) repaint();
}
protected void installListeners()
{
super.installListeners();
getComponent().addFocusListener(this);
}
protected void uninstallListeners()
{
super.uninstallListeners();
getComponent().removeFocusListener(this);
}
}
Usage:
HintTextField field = new HintTextField();
field.setHint("Here's a hint");
This can be achieved by using a focus listener to update the text field content.
Make the class implement the focus listener interface:
class YourClass implements FocusListener
Add a method to catch when focus is gained that blanks the field:
public void focusGained(FocusEvent e) {
if(JTextField1.getText().equals("Username")) {
JTextField1.setText("");
}
}
Add a method to catch when focus is lost to redisplay the default entry if the field was blank:
public void focusLost(FocusEvent e) {
if(JTextField1.getText().equals("")) {
JTextField1.setText("Username");
// you should prevent the form from being processed in this state
// as it will literally contain "Username" for the username
}
}
Register your class as the focus listener for text field:
textField.addFocusListener(this);
Learn more at How to Write a Focus Listener in the Java Tutorials.
Here is a fully working example based on Adam Gawne-Cain's earlier Posting. His solution is simple and actually works exceptionally well.
I've used the following text in a Grid of multiple Fields:
H__|__WWW__+__XXXX__+__WWW__|__H
this makes it possible to easily verify the x/y alignment of the hinted text.
A couple of observations:
- there are any number of solutions out there, but many only work superficially and/or are buggy
- sun.tools.jconsole.ThreadTab.PromptingTextField is a simple solution, but it only shows the prompting text when the Field doesn't have the focus & it's private, but nothing a little cut-and-paste won't fix.
The following works on JDK 8 and upwards:
import java.awt.*;
import java.util.stream.*;
import javax.swing.*;
/**
* #author DaveTheDane, based on a suggestion from Adam Gawne-Cain
*/
public final class JTextFieldPromptExample extends JFrame {
private static JTextField newPromptedJTextField (final String text, final String prompt) {
final String promptPossiblyNullButNeverWhitespace = prompt == null || prompt.trim().isEmpty() ? null : prompt;
return new JTextField(text) {
#Override
public void paintComponent(final Graphics USE_g2d_INSTEAD) {
final Graphics2D g2d = (Graphics2D) USE_g2d_INSTEAD;
super.paintComponent(g2d);
// System.out.println("Paint.: " + g2d);
if (getText().isEmpty()
&& promptPossiblyNullButNeverWhitespace != null) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
final Insets ins = getInsets();
final FontMetrics fm = g2d.getFontMetrics();
final int cB = getBackground().getRGB();
final int cF = getForeground().getRGB();
final int m = 0xfefefefe;
final int c2 = ((cB & m) >>> 1) + ((cF & m) >>> 1); // "for X in (A, R, G, B) {Xnew = (Xb + Xf) / 2}"
/*
* The hint text color should be halfway between the foreground and background colors so it is always gently visible.
* The variables c0,c1,m,c2 calculate the halfway color's ARGB fields simultaneously without overflowing 8 bits.
* Swing sets the Graphics' font to match the JTextField's font property before calling the "paint" method,
* so the hint font will match the JTextField's font.
* Don't think there are any side effects because Swing discards the Graphics after painting.
* Adam Gawne-Cain, Aug 6 2019 at 15:55
*/
g2d.setColor(new Color(c2, true));
g2d.drawString(promptPossiblyNullButNeverWhitespace, ins.left, getHeight() - fm.getDescent() - ins.bottom);
/*
* y Coordinate based on Descent & Bottom-inset seems to align Text spot-on.
* DaveTheDane, Apr 10 2020
*/
}
}
};
}
private static final GridBagConstraints GBC_LEFT = new GridBagConstraints();
private static final GridBagConstraints GBC_RIGHT = new GridBagConstraints();
/**/ static {
GBC_LEFT .anchor = GridBagConstraints.LINE_START;
GBC_LEFT .fill = GridBagConstraints.HORIZONTAL;
GBC_LEFT .insets = new Insets(8, 8, 0, 0);
GBC_RIGHT.gridwidth = GridBagConstraints.REMAINDER;
GBC_RIGHT.fill = GridBagConstraints.HORIZONTAL;
GBC_RIGHT.insets = new Insets(8, 8, 0, 8);
}
private <C extends Component> C addLeft (final C component) {
this .add (component);
this.gbl.setConstraints(component, GBC_LEFT);
return component;
}
private <C extends Component> C addRight(final C component) {
this .add (component);
this.gbl.setConstraints(component, GBC_RIGHT);
return component;
}
private static final String ALIGN = "H__|__WWW__+__XXXX__+__WWW__|__H";
private final GridBagLayout gbl = new GridBagLayout();
public JTextFieldPromptExample(final String title) {
super(title);
this.setLayout(gbl);
final java.util.List<JTextField> texts = Stream.of(
addLeft (newPromptedJTextField(ALIGN + ' ' + "Top-Left" , ALIGN)),
addRight(newPromptedJTextField(ALIGN + ' ' + "Top-Right" , ALIGN)),
addLeft (newPromptedJTextField(ALIGN + ' ' + "Middle-Left" , ALIGN)),
addRight(newPromptedJTextField( null , ALIGN)),
addLeft (new JTextField("x" )),
addRight(newPromptedJTextField("x", "" )),
addLeft (new JTextField(null )),
addRight(newPromptedJTextField(null, null)),
addLeft (newPromptedJTextField(ALIGN + ' ' + "Bottom-Left" , ALIGN)),
addRight(newPromptedJTextField(ALIGN + ' ' + "Bottom-Right", ALIGN)) ).collect(Collectors.toList());
final JButton button = addRight(new JButton("Get texts"));
/**/ addRight(Box.createVerticalStrut(0)); // 1 last time forces bottom inset
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(740, 260));
this.pack();
this.setResizable(false);
this.setVisible(true);
button.addActionListener(e -> {
texts.forEach(text -> System.out.println("Text..: " + text.getText()));
});
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> new JTextFieldPromptExample("JTextField with Prompt"));
}
}