public class ListComboBox extends JFrame {
private String MIS = "MULTIPLE_INTERVAL_SELECTION";
private String SIS = "SINGLE_INTERVAL_SELECTION";
private String SS = "SINGLE_SELECTION";
final int COUNTRIES = 9;
private String[] countries = {"Canada", "China", "Denmark",
"France", "Germany", "India", "Norway", "United Kingdom",
"United States of America"};
private JList<String> jlst = new JList<String>(countries);
private JLabel comboLabel = new JLabel("Choose Selection Mode: ");
private JComboBox jcbo = new JComboBox();
//to hold country labels
private JLabel countryLabel = new JLabel();
public static void main(String[] args) {
ListComboBox frame = new ListComboBox();
frame.setSize(400, 200);
frame.setTitle("Exercise 17.14");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public ListComboBox() {
//Adding selection option to combobox
jcbo.addItem(MIS);
jcbo.addItem(SIS);
jcbo.addItem(SS);
// Register listener combobox
jcbo.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getItem() == MIS) {
jlst.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
if (e.getItem() == SIS) {
jlst.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
if (e.getItem() == SS) {
jlst.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
}
});
//Combobox panel
JPanel combopanel = new JPanel(new FlowLayout());
combopanel.add(comboLabel);
combopanel.add(jcbo);
add(combopanel, BorderLayout.NORTH);
//List panel
JScrollPane listpanel = new JScrollPane(jlst);
add(listpanel, BorderLayout.CENTER);
//Bottom label panel
final JPanel labelpanel = new JPanel();
labelpanel.add(countryLabel);
add(labelpanel, BorderLayout.SOUTH);
//List listener
jlst.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
StringBuilder sb = new StringBuilder(64);
int[] indices = jlst.getSelectedIndices();
int i;
for (i = 0; i < indices.length; i++) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(countries[indices[i]]);
}
countryLabel.setText(sb.toString());
}
});
}
}
Good day, I need your help.
What I need code to do: Add selected country names from the list with scroll bar to the label below the list, remove them as they are unselected in the list.
List selection mode can be switched in JComboBox on top.
Everything works fine, but I cannot figure out the way for country names to properly appear inside the label.
Any tips on how I might accomplish that?
Thanks!
UPDATED!
setName is used for internal identification of the component. Imagin you've been give a list of components, all you know is you need to find the one with some unique identifier, that identifier is supplied via the name property. It has no effect on the output of the component.
You need to use the setText method to change what is displayed on the screen.
The next problem you'll have is setText is a replacement method. That is, it will replace what ever was previously applied with the new value. What might need to do is build a temporary String of the values you want to display and then apply that value to the label, for example...
StringBuilder sb = new StringBuilder(64);
for (i = 0; i < indices.length; i++) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(countries[indices[i]]);
}
countryLabel.setText(sb.toString());
To set text on JLabel use countryLabel.setText instead of countryLabel.setName. Another issue is that in the posted code countryLabel is not added to the frame. I assume it should go into labelpanel, but this part is commented out.
Some other observations:
Do not mix light weight and heavy weight components. See Mixing Heavyweight and Lightweight Components. Instead of ScrollPane use JScrollPane, for example:
JScrollPane listpanel = new JScrollPane(jlst);
Also there is no need to revalidate() the container when you set text on JLabel. The label will be refreshed as a result of setText() method.
Related
I have a class that has 4 private attributes, and through a JComboBox selection, I want to modify them through calling a procedure. However, it seems like even though the JComboBox appears with the selection, the attributes that are shown don't change.
public class PanneauVehicule extends JPanel {
private String[] vehicules;
private int majCarburant;
private int majPassager;
public class PanneauVehicule extends JPanel {
//Main constructor
public PanneauVehicule(){
//Creates a JPanel
super();
//Sets layout as BorderLayout
setLayout(new BorderLayout());
initListeVehicule();
initLabels();
}
public void initListeVehicule(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
//Keep in mind the comboBox does appear with the right selections
add(vehiculesList,BorderLayout.NORTH);
//Here's where it doesnt work.
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
majInfo(2,4);
}
});
}
public void majInfo(int test1, int test2){
this.majCarburant = test2;
this.majPassager = test1;
}
public void initLabels(){
JPanel panneauBas = new JPanel();
panneauBas.setLayout(new GridLayout(2,1,5,5));
JLabel labelCarburant = new JLabel();
labelCarburant.setText("Type de caburant: " + this.majCarburant);
JLabel labelPassagers = new JLabel();
labelPassagers.setText("Nb de passagers: " + this.majPassager);
panneauBas.add(labelPassagers);
panneauBas.add(labelCarburant);
add(panneauBas, BorderLayout.SOUTH);
panneauBas.setBackground(Color.WHITE);
}
After that, I use another procedure that will make majCarburant and majPassager appear on screen. However their values are shown as default (0). I can make their values change manually without using an ActionListener, but the task at hand requires me to use one.
I've been trying ways to just simply change the values through actionListener directly,
You don't invoke an ActionListener directly. Once an ActionListener has been added to the combo box, you can invoke:
setSelectedItem(...) or
setSelectedIndex(...)
on the combo box and the combo box will invoke the ActionListener.
I found the solution after a few more hours of meddling. I just integrated the procedure that creates labels into initListeVehicule, and from there the ActionListener can access the labels to modify their texts.
public void initListeVehiculeInfos(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
add(vehiculesList,BorderLayout.NORTH);
JPanel panneauBas = panelGenerator();
//these setTexts serve as default values before doing your first selection
final JLabel carb = labelGenerator();
carb.setText("Carburant: Kérosène");
final JLabel passager = labelGenerator();
passager.setText("Nb Passager: 110");
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
InterfaceVehicules info = FabriqueVehicule.obtenirVehicule(vehiculesList.getSelectedIndex());
carb.setText("Carburant: " + info.tabNomTypeCarburant[info.getTypeCarburant()] );
passager.setText("Nb Passagers: " + info.getNbPassagersMax());
}
});
panneauBas.add(carb);
panneauBas.add(passager);
add(panneauBas, BorderLayout.SOUTH);
}
It seems like the only way to display text with multiple styles in a text area is to use a JEditorPane. To explore this, I wrote a small app to list all the fonts in their font.
Everything works, and the list is displayed in a JEditorPane, which is inside a JScrollPane.
However, it takes a few seconds to launch and to repopulate, because it generates the entire new list before displaying it. The code is below, following MCV. Minimalizing it to just the message and text made less work so the lag is no longer nearly as noticeable, but my question (below) was more about rendering and keeping track of JScrollPane's position anyway than about this app.
FontFrame.java
public class FontFrame extends JFrame {
private FontFrame() {
JFrame frame = new JFrame("Fonts Displayer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FontPanel fontPanel = new FontPanel();
frame.getContentPane().add(fontPanel);
frame.getRootPane().setDefaultButton(fontPanel.getDefaultButton());
frame.setMinimumSize(new Dimension(600, 600));
frame.setPreferredSize(new Dimension(1000, 700));
frame.pack();
frame.setVisible(true);
}
public static FontFrame launchFontFrame() {
return new FontFrame();
}
public static void main(String[] args) {
FontFrame.launchFontFrame();
}
}
FontPanel.java
class FontPanel extends JPanel {
private String message = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz";
private JEditorPane fontPane;
private JTextField messageInput;
private JButton changeButton;
protected FontPanel() {
buildPanel();
}
private void buildPanel() {
setLayout(new BorderLayout());
// Build message input panel
JPanel inputPanel = new JPanel();
messageInput = new JTextField(message);
messageInput.setFont(new Font("SansSerif", Font.PLAIN, 14));
messageInput.setColumns(40);
JLabel messageLabel = new JLabel("Message:");
changeButton = new JButton("Change");
changeButton.addActionListener((ActionEvent e) -> {
String text = messageInput.getText();
if (!text.isEmpty() && !text.equals(message)) {
message = text;
refreshFontList();
}
});
inputPanel.add(messageLabel);
inputPanel.add(messageInput);
inputPanel.add(changeButton);
// Build scrolling text pane for fonts display
fontPane = new JEditorPane();
fontPane.setContentType("text/html");
fontPane.setEditable(false);
fontPane.setVisible(true);
JScrollPane scrollPane = new JScrollPane(fontPane);
refreshFontList();
// Add components to main panel
add(inputPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
}
private void refreshFontList() {
String[] list = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
StringBuilder messages = new StringBuilder();
// Set global table style settings
messages.append("<table>");
// Make a row for each font
for (String font : list) {
messages.append("<tr>");
//Append data cells
messages.append("<td>").append(font).append("</td>")
.append("<td style=\"font-family:").append(font).append("\">")
.append(message)
.append("</td>");
messages.append("</tr>");
}
messages.append("</table>");
fontPane.setText(messages.toString());
}
JButton getDefaultButton() {
return changeButton;
}
}
Is there any way of redoing refreshFontList so it can generate only what fontPane would show in its viewport first, possibly by using JScrollBar, and then generate the rest of the list right after so the computation time doesn't cause lag in display? Is there a different component that would work better?
I have a program utilizing JTabbedPane. On one pane I have a button that updates an arrayList of objects based on input from the same pane.
What I would like to happen is have the second pane update itself with the object information based on the arrayList in the first pane.
However, I am not sure how to pass the list between the panes. Is there some way to push the array to pane #2 when the update button on the first pane is pressed?
Here is the main file. Instantiating the two tabs
public class Assignment6 extends JApplet
{
private int APPLET_WIDTH = 650, APPLET_HEIGHT = 350;
private JTabbedPane tPane;
private StorePanel storePanel;
private PurchasePanel purchasePanel;
private ArrayList computerList;
public void init()
{
computerList = new ArrayList();
storePanel = new StorePanel(computerList, purchasePanel);
purchasePanel = new PurchasePanel(computerList);
tPane = new JTabbedPane();
tPane.addTab("Store Inventory", storePanel);
tPane.addTab("Customer Purchase", purchasePanel);
getContentPane().add(tPane);
setSize (APPLET_WIDTH, APPLET_HEIGHT); //set Applet size
}
}
The first panel instantiates a button listener that applies all of the logic to the array list "compList"
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//Add Computer to list
Computer comp = new Computer();
comp.setBrandName(brandField.getText());
comp.setPrice(Double.parseDouble(priceField.getText()));
comp.setMemory(Integer.parseInt(memoryField.getText()));
comp.setCPU(typeField.getText(), Integer.parseInt(speedField.getText()));
compList.add(comp);
}
stringField.setText(listString);
alertLabel.setText("Computer Added");
}
}
Here is the other pane. The for loop at the end is what I need to push the arrayList to. After it receives the list, it populates a box with a checkbox for each object in the list
public PurchasePanel(ArrayList compList)
{
west = new JPanel();
east = new JPanel();
totalField = new JTextField();
this.compList = compList;
setLayout(new GridLayout(0,2));
add(west);
add(east);
east.setLayout(new BorderLayout());
east.add(currentTotalLabel, BorderLayout.NORTH);
east.add(totalField, BorderLayout.CENTER);
west.setLayout( new BoxLayout(west, BoxLayout.Y_AXIS));
for(Object c : compList){
System.out.println("Made it");
NumberFormat fmt = NumberFormat.getCurrencyInstance();
String str = ("BrandName:" + (((Computer) c).getBrandName() +"CPU:" + (((Computer) c).getCPU() +"Memory:" + ((Computer) c).getMemory() + "M" +"Price:" + fmt.format(((Computer) c).getPrice()))));
JCheckBox chk = new JCheckBox(str);
west.add(chk);
}
}
}
You can use the same listener used to update the first ArrayList, to update the second pane. Something like:
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Update the first ArrayList
// Update the second pane
}
I am new to java swing. I have a code that generates checkboxes. I want to have a button somewhere in my frame, which on clicking, should delete the selected checkbox entries. Here is what I have so far.
public class Scroll extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("JFrame with ScrollBar");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ResultButtonBar();
newContentPane.setOpaque(true);
JScrollPane scrollPane = new JScrollPane(newContentPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.getContentPane().add(scrollPane);
frame.setSize(800, 800);
frame.setVisible(true);
JButton startButton = new JButton("Start");
frame.add(startButton, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null, "basdsadad");
}
});
}
}
and the new ResultButtonBar().java
public class ResultButtonBar extends JPanel {
private HashMap<JCheckBox, ArrayList<Integer>> map = new HashMap<>();
private JLabel _label;
private static final int MAX_CHECKS = 1000;
public ResultButtonBar() {
super();
JButton btn = new JButton();
btn.setVisible(true);
JCheckBox checkBox;
Random r = new Random();
JPanel checkPanel = new JPanel(new GridLayout(0, 1));
_label = new JLabel("You selected nothing");
checkPanel.add(_label);
for (int i = 0; i < MAX_CHECKS; i++) {
StringBuilder sb = new StringBuilder();
ArrayList<Integer> a = new ArrayList<>();
for (int j = 0; j < 2; j++) {
Integer temp = (r.nextInt()) % 100;
a.add(temp);
sb.append(temp).append(" ");
}
checkBox = new JCheckBox(sb.toString().trim());
checkBox.setName("CheckBox" + i);
map.put(checkBox, a);
checkPanel.add(checkBox);
}
add(checkPanel);
}
}
First of all, keep all your check boxes in an ArrayList so you will have a reference to them when you need it.
Then, add a JButton wherever you need. Then iterate over this ArrayList and call invalidate() on the component which contains your check boxes. Next statement would be to call the remove() method on the container; the checkPanel.
Alternatively, you may call removeAll() if all the components in the container are check boxes and you want to remove them.
The alternative pointed by StanislavL is also a good one if you have a lot of different components along with check boxes
I can think of two approaches:
if You are maintaining one JPanel instance which contains only the instances of JCheckBox, then you can first get all the checkbox's using panel.getComponents() method, check their selection state and depending on the state remove it by calling panel.remove(component). For example:
Component checkBox[] = checkBoxPanel.getComponents();
for(Component c:checkBox)
if(((JCheckBox)c).isSelected())
checkBoxPanel.remove(c);
checkBoxPanel.revalidate();
checkBoxPanel.repaint();
The last call revalidate() and repaint() on the checkBoxPanel is important for reflecting changes on the layout and graphics rendering of the components.
You can use ItemListener with the instances of JCheckBox to do things on selection state change. Use an instance of ArrayList<JCheckBox> to add the selected checkBox to the list. However you should use an implemented ItemListener: MyItemListener implements ItemListener and create one instance and add this instances to all the checkboxes to react on state change. You can use event source e.getSource() to get the JCheckBox instance on which the ItemEvent is performed.
Tutorial resource:
How to Write an Item Listener
I'm very new to Java.
I've created two JLists in which you can add and remove 'shopping cart' items.
Once the user has added all their items they can click a submit button to view their selected items in a new window.
My first list is itemList (populated with items from array), the second list is shoppinglist which gets populated with whatever the user selects with a JButton.
Additional arrays are created to handle the actions of the buttons moving the items to and from the JLists. I've tried a few things, but haven't been successful in showing the items that get selected and shown in shopinglist to appear in a new window once submit is hit.
Any help is much appreciated.
//Create itemList
itemList = new JList(shopping);
contentPane.add(itemList);
itemList.setVisibleRowCount(10);
itemList.setFixedCellHeight(20);
itemList.setFixedCellWidth(140);
itemList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list1 = new JScrollPane(itemList);
//contentPane.add(list1);
//Create shoppingList
shoppingList = new JList(items);
contentPane.add(shoppingList);
shoppingList.setVisibleRowCount(10);
shoppingList.setFixedCellHeight(20);
shoppingList.setFixedCellWidth(140);
shoppingList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//Add JScrollPane to maintain size
JScrollPane list2 = new JScrollPane(shoppingList);
JPanel buttonPanel = new JPanel();
//contentPane.add(list2);
Buttonin = new JButton(">>");
//Buttonin.setBounds(144, 46, 60, 23);
Buttonin.addActionListener(this);
buttonPanel.add(Buttonin);
ButtonOut = new JButton("<<");
//ButtonOut.setBounds(144, 80, 60, 23);
ButtonOut.addActionListener(this);
buttonPanel.add(ButtonOut);
JPanel submitPanel = new JPanel();
submitButton = new JButton("Submit");
submitPanel.add(submitButton);
submitButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent az) {
JFrame frame = new JFrame ("Go Shopping!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyPanel2());
frame.pack();
frame.setVisible(true);
}
});
contentPane.add(list1);
contentPane.add(buttonPanel);
contentPane.add(list2);
contentPane.setOpaque(true);
contentPane.add(submitPanel);
return contentPane;
}
public void actionPerformed(ActionEvent e)
{
int i = 0;
//When in buttonin is pressed index and value of selected item is output to array
if (e.getSource() == Buttonin)
{
int[] fromindex = itemList.getSelectedIndices();
Object[] from = itemList.getSelectedValues();
//add items to the shoppingList
for (i = 0; i < from.length; i++)
{
items.addElement(from[i]);
}
//Must remove items that are selected from the itemList
for (i = (fromindex.length-1); i >= 0; i--)
{
shopping.remove(fromindex[i]);
}
}
//When out button is pressed index and value of selected item is output to new array
else if (e.getSource() == ButtonOut)
{
Object[] to = shoppingList.getSelectedValues();
int [] toindex = shoppingList.getSelectedIndices();
//add items to previous list
for(i = 0; i < to.length; i++)
{
shopping.addElement(to[i]);
}
//Must remove what's deselected
for (i = (toindex.length-1); i >= 0; i--)
{
items.remove(toindex[i]);
}
}
Ok, bear with me (very very new to java) is this how I would set up the constructor to reference to ProfileFrame objects? And if so how do I change my main to reflect the new constructor?
public class GoShopping extends JPanel {
private JList shopList;
public GoShopping(ProfileFrame slist) {
//construct components
shopList = new JList(slist.getListModel());
shopList.setBounds(6, 6, 123, 166);//don't worry I'm changing the layout
add(shopList);
}
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//I need new GoShopping to reflect the new constructor, but not sure how to make it work
frame.getContentPane().add (new GoShopping());
frame.pack();
frame.setVisible (true);
}
}
You're creating a new ProfileFrame object in your MyPanel2 constructor, and since this is not the same instance as the visualized ProfileFrame object, then its JList's model will be null. A bad solution is to use static variables -- just don't do this please. A better solution is to pass a reference to the true visualized ProfileFrame object into your MyPanel2 constructor and call the public methods off of this instance.
And again, don't use null layout and setBounds(...), but instead use the layout managers unless you like making things more difficult than they need to be.