JOptionsPane displays Components in the 'options' argument as Component.toString() - java

I'm trying to pop up a dialog to allow the user to select one of two colors as a background color. To make it look especially spiffy, I'd like to two choices to be displayed in the color in question, i.e.:
import java.awt.Color;
import java.awt.Label;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class JOptionPaneTest extends JFrame{
public static void main(String[] args) {
new JOptionPaneTest();
}
public JOptionPaneTest() {
Object[] possibilities = new Object[2];
JButton black = new JButton("Black");
JButton white = new JButton("White");
black.setBackground(Color.black);
white.setBackground(Color.white);
black.setForeground(Color.white);
white.setForeground(Color.black);
possibilities[0] = black;
possibilities[1] = white;
JButton l = (JButton)JOptionPane.showInputDialog(this,
"Please specify the background color", "Background check",
JOptionPane.QUESTION_MESSAGE, null, possibilities,
possibilities[0]);
System.out.println("" + l);
}
}
However, this doesn't work - it displays the JButton.toString() return values in a drop down instead of the JButton. I also tried JLabel and Label for the heck of it. According to the API, the JButtons should be added to the dialog as is since they're Components. If I add the JButton to the 'message' parameter it does display as expected.
Any idea what I'm doing wrong?

The Java API is slighly unclear about this point. At the top describes how to interpret the options, but options are the YES, NO, CANCEL... possibilities the user can choose, painted in the buttons row. You are talking about the selectionValues, and then the API (go to last method named showInputDialog) is clear:
selectionValues - an array of Objects that gives the possible selections
It is up to the UI to decide how best to represent the selectionValues, but usually a JComboBox, JList, or JTextField will be used.
From my experience, the objects passed in the selectionValues are displayed using toString()and the result is shown in a JComboBox or a JList, so you can not show selection values with custom painting; you need to implement you own dialog for that.
You can pass the message as a Component so you can provide a legend to the user about the selectionValues, where you can show labels with background colors to indicate each color available and thus provide assitance selecting a value from selectionValues.

Should be array of strings not array of jbutton (possibilites) in showInputDialog, but in this way you won't have background color. I don't think it exists any way to implement such colors chooser in showInputDialog()
String[] str = {"aaa", "bbb"};
JButton l = (JButton)JOptionPane.showInputDialog(this,
"Please specify the background color", "Background check",
JOptionPane.QUESTION_MESSAGE, null, str, str[0]);

Related

How do I make a text fields horizontal and non-editable?

I have this applet that will add 2 numbers together and display their sum in a third text box.
https://pastebin.com/4ga1brD1
I want the text boxes to be arranged horizontally but more importantly I need the third text box to be uneditable.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Question extends Applet implements ActionListener
{
TextField firstNum, secondNum, resultNum;
public Question()
{
setLayout(new GridLayout(3, 2, 10, 15));
setBackground(Color.cyan);
firstNum = new TextField(15);
secondNum = new TextField(15);
resultNum = new TextField(15);
secondNum.addActionListener(this);
add(new Label("Enter First Number"));
add(firstNum);
add(new Label("Enter Second Number"));
add(secondNum);
add(new Label("S U M"));
add(resultNum);
}
public void actionPerformed(ActionEvent e)
{
String str1 = firstNum.getText();
double fn = Double.parseDouble(str1);
double sn = Double.parseDouble(secondNum.getText());
resultNum.setText("Sum is " + (fn+sn));
}
}
To arrange your TextField components horizontally, don't add them directly to the Applet. Instead, create a Panel, give it a FlowLayout and add your TextField components to the Panel. Then you can add the Panel directly to your Applet. Make sure your Applet is wide enough to fit all three boxes side by side or the layout will stack the third box under the first one.
Note: I would test this for you, but no browser has supported Applets for at least five years.
To make the third TextField uneditable, you want to use the setEnabled() method. setEditable() would be the way to accomplish the same thing if you were using JTextField, as opposed to the simple AWT TextField that you're using. You should get in the habit of looking at the official documentation, where the answer is readily found.
resultNum.setEnabled(false);
Bear in mind that a disabled box will appear greyed out, which may be visually unappealing. The solution is to convert to Java Swing, which will allow you to use setEditable, which simply prevents your user from clicking into the box without changing the appearance. Swing would also allow you to use layout managers with much more sophistication and flexibility.

Why Is My TextField Not Being The Size I Have Commanded It To Be?

I cannot figure out why my TextField is refusing to be the size I have demanded that it be. I was hoping to get some insight from you guys.
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.TextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class HW09 extends JFrame{
public HW09() {
this.setVisible(true);
this.setSize(455, 155);
TextField cartonsPerShipmentBox = new TextField("5");
cartonsPerShipmentBox.setMaximumSize(new Dimension(20, 20));
Button calculateButton = new Button("Calculate!");
JPanel middleContainer = new JPanel();
middleContainer.setLayout(new GridLayout(2, 4));
middleContainer.add(new JLabel("Cartons Per Shipment: "));
//CARTON AMOUNT
middleContainer.add(cartonsPerShipmentBox);
//TOTAL BOX
middleContainer.add(new JLabel("Total: "));
middleContainer.add(new JLabel("Items per carton: "));
//ITEMS PER CARTON BOX
middleContainer.add(new Button("OOF"));
//CALCULATE BUTTON
middleContainer.add(calculateButton);
this.add(middleContainer);
}
public static void main(String[] args) {
HW09 hw = new HW09();
}
}
I want this because even though my items are in a grid layout, the TextField is really just too dang big for what I want and it makes the program look weird. I want the textfield to be pretty small, as I signified with the dimension(20, 20). However, when I run the program it makes the TextField the same size as every other item.
The reason the width is not set to your preferred width is that the integer argument passed to the TextField constructor, 5 in the example, indicates the number of columns in the field. This number is used along with metrics provided by the field's current font to calculate the field's preferred width. It does not limit the number of characters the user can enter. To do that, you can either use a formatted text field or a document listener.
Try reducing the column width.
That is how GridLayOut works in Swing. it will give equal width to all components in it.
If you want more controlled behavior, then go for GridBagLayOut
You can check the following link:
Java change JTextField size inside a GridLayout

change font in JOptionPane.showInputDialog

I'm writing a program in java language and I want to make some changes in one part of my JOptionPane.showInputDialog. My dialog is this :
JOptionPane.showInputDialog("Total Amount Deposited:\t\t" +
totalAmount + "\n Enter Coin Value \n" + "(Enter 1 to stop)");
and I want to make the part that is saying (Enter 1 to stop) a little bit smaller than the other parts.
I'm beginner in java language (roughly 2 months :D) and don't have any other experience. so, please keep your answers simple. thanks in advance.
A JOptionPane will display the text in a JLabel, which supports basic HTML. So you will need to wrap your text string in HTML, then you can use different fonts, colors or whatever.
Simple example:
String text = "<html>Normal text <b>and bold text</b></html>";
JOptionPane.showInputDialog(text);
You can also use Font.pointSize() or Font.size() from java.awt.Font.
Create a String = "the text"
put in a label pa
use setFont();
Quick example :
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Test extends JFrame {
public static void main(String[] args)
{
String a = "(enter 1 to stop)";
JLabel pa = new JLabel();
JFrame fr = new JFrame();
fr.setSize(200,200);
pa.setText(a);
pa.setFont(pa.getFont().deriveFont(11.0f)); //change the font size from here
fr.add(pa);
fr.setVisible(true);
}
}
For JDK 8.x, I find the following works to enlarge the font size of most portions of the built-in JOptionPane.showInputDialog, especially buttons, textboxes and comboboxes.
It is mostly generic, except for the two parts I want to be bold font.
It even allows for exceptions (think of it as an "all except" strategy) when you want to enlarge 99% of the pieces of an input dialog, except for one or two pieces.
Sorry for the bad formatting, but the "Code Sample" tool messed up everything and I don't have time to fix it.
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.*;
/**
* Changes the font size used in JOptionPane.showInputDialogs to make them more
* ADA section 508 compliant by making the text size larger, which is very nice
* for older people and anyone else with vision problems.
*
* #param fontSize
* - size of the font in pixels
*/
private static void makeDialogsEasierToSee(int fontSize)
{
// This next one is very strange; but, without it,
// any subsequent attempt to set InternalFrame.titleFont will
// be ignored, so resist the temptation to remove it.
JDialog.setDefaultLookAndFeelDecorated(true);
// define normal and bold fonts that we will use to override the defaults
Font normalFont = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
Font boldFont = normalFont.deriveFont(Font.BOLD);
// get a list of objects that we can try to adjust font size and style for
List<Map.Entry<Object, Object>> entries = new ArrayList<>(UIManager.getLookAndFeelDefaults().entrySet());
// System.out.println(entries.size());
// remove anything that does NOT involve font selection
entries.removeIf(filter -> filter.getKey().toString().indexOf(".font") == -1);
// System.out.println(entries.size());
// Define a list of font sections of the screen that we do NOT want to
// enlarge/bold.
// The following is specific to jKarel so we do not obscure the display of
// "beeper piles" on the maps.
List<String> exempt = Arrays.asList("Panel.font");
// remove anything on the exempt list
entries.removeIf(filter -> exempt.contains(filter.getKey().toString()));
// System.out.println(entries.size());
// optional: sort the final list
Collections.sort(entries, Comparator.comparing(e -> Objects.toString(e.getKey())));
// apply normal font to all font objects that survived the filters
for (Map.Entry<Object, Object> entry : entries)
{
String key = entry.getKey().toString();
// System.out.println(key);
UIManager.put(key, normalFont);
}
UIManager.put("Label.font", boldFont);
UIManager.put("InternalFrame.titleFont", boldFont);
}
You basically have two straightforward options - Switch to JDialog or use HTML.
JOptionPane is intended for simple messages or interaction with the users. JDialog is a better choice if you want to break out of the canned use cases, and as you get more complex you will probably eventually have to switch to it.
To meet your immediate use case, you can send in an html message. The rules are:
You must begin and end with <html></html> tags. Put them in the middle and nothing happens.
You must remove all "\n"'s in your code. They don't work in html
anyway and the JPanel tries to use each line, as defined by \n's as a
separate html doc. Switch to
int totalAmount = 345; //for testing
String message = "<html>"
+ "Total Amount Deposited: " + totalAmount
+ "<br> Enter Coin Value "
+ "<br><span style='font-size:10'>(Enter 1 to stop)</span>"
+ "</html>";
JOptionPane.showInputDialog(message);

GWT - Google visualization problems using layout panels?

I'm having troubles in my GWT app with a Google Visualization chart not showing up until after the user has some sort of interaction with the window (e.g. moves the mouse across the screen or presses a button). This would be fine except that the chart is suppose to show up as the first thing the user sees and since it's meant to be seen on a mobile device, it's likely they will not see the chart because their first interaction will be clicking a button that hides the chart to show other information.
Using the "Getting started tutorial" over at the Visualization code's page, the chart loads immediately fine (once some slight changes are made the fix the problems from the slightly out of date tutorial). After some trial and error to find where the difference between my code and the example code that was causing the problem, I found that it's happening because my code is using the newer layout panels instead of just regular panels in GWT.
The below code is the working tutorial code changed so that it uses a RootLayoutPanel.get() instead of a RootPanel.get(). With this, the chart doesn't load until you click to reload the page, then you can see the chart for an instant before the page reloads. This should be easily tested with the below code. To get the chart to show up for the entire time, simply change RootLayoutPanel.get() to RootPanel.get().
Something in my app is allowing the chart to load after user interaction (I'm not sure what). However, the layout panel is certainly the problem as if I change it to a regular panel it works fine. Unfortunately, my entire app is built using layout panels.
What's going on and how might I be able to make the chart show up from the start using layout panels? Thank you much!
package com.test.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Selection;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.events.SelectHandler;
import com.google.gwt.visualization.client.visualizations.corechart.PieChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
public class SimpleViz implements EntryPoint {
public void onModuleLoad() {
// Create a callback to be called when the visualization API
// has been loaded.
Runnable onLoadCallback = new Runnable() {
public void run() {
LayoutPanel panel = RootLayoutPanel.get();
// Create a pie chart visualization.
PieChart pie = new PieChart(createTable(), createOptions());
pie.addSelectHandler(createSelectHandler(pie));
panel.add(pie);
}
};
// Load the visualization api, passing the onLoadCallback to be called
// when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
}
private Options createOptions() {
Options options = Options.create();
options.setWidth(400);
options.setHeight(240);
options.setTitle("My Daily Activities");
return options;
}
private SelectHandler createSelectHandler(final PieChart chart) {
return new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
String message = "";
// May be multiple selections.
JsArray<Selection> selections = chart.getSelections();
for (int i = 0; i < selections.length(); i++) {
// add a new line for each selection
message += i == 0 ? "" : "\n";
Selection selection = selections.get(i);
if (selection.isCell()) {
// isCell() returns true if a cell has been selected.
// getRow() returns the row number of the selected cell.
int row = selection.getRow();
// getColumn() returns the column number of the selected cell.
int column = selection.getColumn();
message += "cell " + row + ":" + column + " selected";
} else if (selection.isRow()) {
// isRow() returns true if an entire row has been selected.
// getRow() returns the row number of the selected row.
int row = selection.getRow();
message += "row " + row + " selected";
} else {
// unreachable
message += "Pie chart selections should be either row selections or cell selections.";
message += " Other visualizations support column selections as well.";
}
}
Window.alert(message);
}
};
}
private AbstractDataTable createTable() {
DataTable data = DataTable.create();
data.addColumn(ColumnType.STRING, "Task");
data.addColumn(ColumnType.NUMBER, "Hours per Day");
data.addRows(2);
data.setValue(0, 0, "Work");
data.setValue(0, 1, 14);
data.setValue(1, 0, "Sleep");
data.setValue(1, 1, 10);
return data;
}
}
With the Layout panels the sizing of the widgets is done in JavaScript. When the initial page is loaded the initial sizing is done after everything else is finished. However in your case the pie is added when the library is loaded and that runs after the initial sizing. Therefor your widget isn't sized and won't show up. You need to call panel.forceLayout(); explicitly as the last method in you run method.
The google chart tools definately work with LayoutPanels. I am using it myself.
It's really difficult to say what's wrong but here are a couple of suggestions:
Check with Chrome Dev Tools (Console) if an exception is thrown.
Do you have standard mode enabled. That's important with LayoutPanels (make sure you have <!DOCTYPE html> in your HTML host page
You could try a 3rd party wrapper (supports automatic resizes)

Example text in JTextField

I am looking for a way to put example text into a swing JTextField and have it grayed out. The example text should then disappear as soon as any thing is entered into that text field. Some what similar to what stackoverflow does when a user is posting a question with the title field.
I would like it if it was already a extended implementation of JTextField so that I can just drop it in as a simple replacement. Anything from swingx would work. I guess if there is not an easy way to do this my option will probably be to override the paint method of JTextField do something that way maybe.
Thanks
The Text Prompt class provides the required functionality without using a custom JTextField.
It allows you to specify a prompt that is displayed when the text field is empty. As soon as you type text the prompt is removed.
The prompt is actually a JLabel so you can customize the font, style, colour, transparency etc..:
JTextField tf7 = new JTextField(10);
TextPrompt tp7 = new TextPrompt("First Name", tf7);
tp7.setForeground( Color.RED );
Some examples of customizing the look of the prompt:
If you can use external librairies, the Swing components from Jide software have what you are looking for; it's called LabeledTextField (javadoc) and it's part of the JIDE Common Layer (Open Source Project) - which is free. It's doing what mklhmnn suggested.
How about initialize the text field with default text and give it a focus listener such that when focus is gained, if the text .equals the default text, call selectAll() on the JTextField.
Rather than overriding, put a value in the field and add a KeyListener that would remove the value when a key stroke is registered. Maybe also have it change the foreground.
You could wrap this up into your own custom JTextField class that would take the default text in a constructor.
private JLabel l;
JPromptTextField(String prompt) {
l = new JLabel(prompt, SwingConstants.CENTER);
l.setForeground(Color.GRAY);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (this.getText().length() == 0) {
// Reshape the label if needed, then paint
final Rectangle mine = this.getBounds();
final Rectangle its = l.getBounds();
boolean resized = (mine.width != its.width) || (mine.height != its.height);
boolean moved = (mine.x != its.x) || (mine.y != its.y);
if (resized || moved)
l.setBounds(mine);
l.paint(g);
}
}
You can't do that with a plain text field, but you can put a disabled JLabel on top of the JTextField and hide it if the text field gets the focus.
Do it like this:
Define the string with the initial text you like and set up your TextField:
String initialText = "Enter your initial text here";
jTextField1.setText(initialText);
Add a Focus Listener to your TextField, which selects the entire contents of the TextField if it still has the initial value. Anything you may type in will replace the entire contents, since it is selected.
jTextField1.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
if (jTextField1.getText().equals(initialText)) {
jTextField1.selectAll();
}
}
});

Categories