mirror of https://github.com/weisJ/darklaf.git
weisj
5 years ago
11 changed files with 1300 additions and 1 deletions
@ -0,0 +1,313 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2019 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all |
||||
* copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
* SOFTWARE. |
||||
*/ |
||||
package com.weis.darklaf.ui.optionpane; |
||||
|
||||
import org.jetbrains.annotations.Contract; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import sun.swing.DefaultLookup; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.border.Border; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import javax.swing.plaf.basic.BasicOptionPaneUI; |
||||
import java.awt.*; |
||||
|
||||
public class DarkOptionPaneUI extends BasicOptionPaneUI { |
||||
|
||||
|
||||
@NotNull |
||||
@Contract("_ -> new") |
||||
public static ComponentUI createUI(final JComponent x) { |
||||
return new DarkOptionPaneUI(); |
||||
} |
||||
|
||||
@Override |
||||
protected void installDefaults() { |
||||
super.installDefaults(); |
||||
} |
||||
|
||||
@Override |
||||
protected Container createButtonArea() { |
||||
JPanel bottom = new JPanel(); |
||||
Border border = (Border) DefaultLookup.get(optionPane, this, "OptionPane.buttonAreaBorder"); |
||||
bottom.setName("OptionPane.buttonArea"); |
||||
if (border != null) { |
||||
bottom.setBorder(border); |
||||
} |
||||
bottom.setLayout(new DarkButtonAreaLayout( |
||||
DefaultLookup.getBoolean(optionPane, this, "OptionPane.sameSizeButtons", false), |
||||
DefaultLookup.getInt(optionPane, this, "OptionPane.buttonPadding", 6), |
||||
DefaultLookup.getInt(optionPane, this, "OptionPane.buttonOrientation", SwingConstants.CENTER), |
||||
DefaultLookup.getBoolean(optionPane, this, "OptionPane.isYesLast", false))); |
||||
addButtonComponents(bottom, getButtons(), getInitialValueIndex()); |
||||
return bottom; |
||||
} |
||||
|
||||
protected boolean getSizeButtonsToSameWidth() { |
||||
return UIManager.getBoolean("OptionPane.sameSizeButtons"); |
||||
} |
||||
|
||||
/** |
||||
* <code>ButtonAreaLayout</code> behaves in a similar manner to |
||||
* <code>FlowLayout</code>. It lays out all components from left to |
||||
* right. If <code>syncAllWidths</code> is true, the widths of each |
||||
* component will be set to the largest preferred size width. |
||||
* <p> |
||||
* This class should be treated as a "protected" inner class. |
||||
* Instantiate it only within subclasses of {@code BasicOptionPaneUI}. |
||||
*/ |
||||
public static class DarkButtonAreaLayout extends ButtonAreaLayout { |
||||
protected boolean syncAllWidthOverwrite = false; |
||||
private int orientation; |
||||
private boolean reverseButtons; |
||||
/** |
||||
* Indicates whether or not centersChildren should be used vs |
||||
* the orientation. This is done for backward compatibility |
||||
* for subclassers. |
||||
*/ |
||||
private boolean useOrientation; |
||||
|
||||
public DarkButtonAreaLayout(final boolean syncAllSizes, final int padding, final int orientation, |
||||
final boolean reverseButtons) { |
||||
this(syncAllSizes, padding); |
||||
useOrientation = true; |
||||
this.orientation = orientation; |
||||
this.reverseButtons = reverseButtons; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new instance of {@code ButtonAreaLayout}. |
||||
* |
||||
* @param syncAllWidths if the width of children should be synchronized |
||||
* @param padding the padding value |
||||
*/ |
||||
public DarkButtonAreaLayout(final boolean syncAllWidths, final int padding) { |
||||
super(syncAllWidths, padding); |
||||
this.syncAllWidths = syncAllWidths; |
||||
this.padding = padding; |
||||
centersChildren = true; |
||||
useOrientation = false; |
||||
} |
||||
|
||||
/** |
||||
* Sets if the width of children should be synchronized. |
||||
* |
||||
* @param newValue if the width of children should be synchronized |
||||
*/ |
||||
public void setSyncAllWidths(final boolean newValue) { |
||||
syncAllWidths = newValue; |
||||
} |
||||
|
||||
/** |
||||
* Returns if the width of children should be synchronized. |
||||
* |
||||
* @return if the width of children should be synchronized |
||||
*/ |
||||
public boolean getSyncAllWidths() { |
||||
return syncAllWidths && !syncAllWidthOverwrite; |
||||
} |
||||
|
||||
/** |
||||
* Sets the padding value. |
||||
* |
||||
* @param newPadding the new padding |
||||
*/ |
||||
public void setPadding(final int newPadding) { |
||||
this.padding = newPadding; |
||||
} |
||||
|
||||
/** |
||||
* Returns the padding. |
||||
* |
||||
* @return the padding |
||||
*/ |
||||
public int getPadding() { |
||||
return padding; |
||||
} |
||||
|
||||
/** |
||||
* Sets whether or not center children should be used. |
||||
* |
||||
* @param newValue a new value |
||||
*/ |
||||
public void setCentersChildren(final boolean newValue) { |
||||
centersChildren = newValue; |
||||
useOrientation = false; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether or not center children should be used. |
||||
* |
||||
* @return whether or not center children should be used |
||||
*/ |
||||
public boolean getCentersChildren() { |
||||
return centersChildren; |
||||
} |
||||
|
||||
private int getOrientation(final Container container) { |
||||
if (!useOrientation) { |
||||
return SwingConstants.CENTER; |
||||
} |
||||
if (container.getComponentOrientation().isLeftToRight()) { |
||||
return orientation; |
||||
} |
||||
switch (orientation) { |
||||
case SwingConstants.LEFT: |
||||
return SwingConstants.RIGHT; |
||||
case SwingConstants.RIGHT: |
||||
return SwingConstants.LEFT; |
||||
case SwingConstants.CENTER: |
||||
return SwingConstants.CENTER; |
||||
} |
||||
return SwingConstants.LEFT; |
||||
} |
||||
|
||||
public void addLayoutComponent(final String string, final Component comp) { |
||||
} |
||||
|
||||
public void layoutContainer(final Container container) { |
||||
Component[] children = container.getComponents(); |
||||
|
||||
if (children != null && children.length > 0) { |
||||
int numChildren = children.length; |
||||
Insets insets = container.getInsets(); |
||||
int maxWidth = 0; |
||||
int maxHeight = 0; |
||||
int totalButtonWidth = 0; |
||||
int x = 0; |
||||
int xOffset = 0; |
||||
boolean ltr = container.getComponentOrientation().isLeftToRight(); |
||||
boolean reverse = (ltr) == reverseButtons; |
||||
|
||||
for (Component child : children) { |
||||
Dimension pref = child.getPreferredSize(); |
||||
maxWidth = Math.max(maxWidth, pref.width); |
||||
maxHeight = Math.max(maxHeight, pref.height); |
||||
totalButtonWidth += pref.width; |
||||
} |
||||
if (getSyncAllWidths()) { |
||||
int totalButtonWidthTmp = maxWidth * numChildren; |
||||
totalButtonWidthTmp += (numChildren - 1) * padding; |
||||
|
||||
syncAllWidthOverwrite = totalButtonWidthTmp > container.getWidth(); |
||||
if (!syncAllWidthOverwrite) { |
||||
totalButtonWidth = totalButtonWidthTmp; |
||||
} |
||||
} else { |
||||
totalButtonWidth += (numChildren - 1) * padding; |
||||
} |
||||
|
||||
|
||||
switch (getOrientation(container)) { |
||||
case SwingConstants.LEFT: |
||||
x = insets.left; |
||||
break; |
||||
case SwingConstants.RIGHT: |
||||
x = container.getWidth() - insets.right - totalButtonWidth; |
||||
break; |
||||
case SwingConstants.CENTER: |
||||
if (getCentersChildren() || numChildren < 2) { |
||||
x = (container.getWidth() - totalButtonWidth) / 2; |
||||
} else { |
||||
x = insets.left; |
||||
if (getSyncAllWidths()) { |
||||
xOffset = (container.getWidth() - insets.left - |
||||
insets.right - totalButtonWidth) / |
||||
(numChildren - 1) + maxWidth; |
||||
} else { |
||||
xOffset = (container.getWidth() - insets.left - |
||||
insets.right - totalButtonWidth) / |
||||
(numChildren - 1); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
|
||||
for (int counter = 0; counter < numChildren; counter++) { |
||||
int index = (reverse) ? numChildren - counter - 1 : |
||||
counter; |
||||
Dimension pref = children[index].getPreferredSize(); |
||||
|
||||
if (getSyncAllWidths()) { |
||||
children[index].setBounds(x, insets.top, maxWidth, maxHeight); |
||||
} else { |
||||
children[index].setBounds(x, insets.top, pref.width, pref.height); |
||||
} |
||||
if (xOffset != 0) { |
||||
x += xOffset; |
||||
} else { |
||||
x += children[index].getWidth() + padding; |
||||
} |
||||
} |
||||
} |
||||
syncAllWidthOverwrite = false; |
||||
} |
||||
|
||||
public Dimension minimumLayoutSize(final Container c) { |
||||
if (c != null) { |
||||
Component[] children = c.getComponents(); |
||||
|
||||
if (children != null && children.length > 0) { |
||||
Dimension aSize; |
||||
int numChildren = children.length; |
||||
int height = 0; |
||||
Insets cInsets = c.getInsets(); |
||||
int extraHeight = cInsets.top + cInsets.bottom; |
||||
int extraWidth = cInsets.left + cInsets.right; |
||||
|
||||
if (getSyncAllWidths()) { |
||||
int maxWidth = 0; |
||||
|
||||
for (Component child : children) { |
||||
aSize = child.getPreferredSize(); |
||||
height = Math.max(height, aSize.height); |
||||
maxWidth = Math.max(maxWidth, aSize.width); |
||||
} |
||||
return new Dimension(extraWidth + (maxWidth * numChildren) + |
||||
(numChildren - 1) * padding, |
||||
extraHeight + height); |
||||
} else { |
||||
int totalWidth = 0; |
||||
|
||||
for (Component child : children) { |
||||
aSize = child.getPreferredSize(); |
||||
height = Math.max(height, aSize.height); |
||||
totalWidth += aSize.width; |
||||
} |
||||
totalWidth += ((numChildren - 1) * padding); |
||||
return new Dimension(extraWidth + totalWidth, extraHeight + height); |
||||
} |
||||
} |
||||
} |
||||
return new Dimension(0, 0); |
||||
} |
||||
|
||||
public Dimension preferredLayoutSize(final Container c) { |
||||
return minimumLayoutSize(c); |
||||
} |
||||
|
||||
public void removeLayoutComponent(final Component c) { |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,192 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2019 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all |
||||
* copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
* SOFTWARE. |
||||
*/ |
||||
|
||||
package dialog; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.text.DefaultFormatterFactory; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.ComponentAdapter; |
||||
import java.awt.event.ComponentEvent; |
||||
import java.awt.event.WindowAdapter; |
||||
import java.awt.event.WindowEvent; |
||||
import java.beans.PropertyChangeEvent; |
||||
import java.beans.PropertyChangeListener; |
||||
import java.text.ParseException; |
||||
|
||||
/* 1.4 example used by DialogDemo.java. */ |
||||
class CustomDialog extends JDialog implements ActionListener, PropertyChangeListener { |
||||
private String typedText = null; |
||||
private JFormattedTextField textField; |
||||
private DialogDemo dd; |
||||
|
||||
private String magicWord; |
||||
private JOptionPane optionPane; |
||||
|
||||
private String btnString1 = "Enter"; |
||||
private String btnString2 = "Cancel"; |
||||
|
||||
/** |
||||
* Creates the reusable dialog. |
||||
*/ |
||||
public CustomDialog(final Frame aFrame, final String aWord, final DialogDemo parent) { |
||||
super(aFrame, true); |
||||
dd = parent; |
||||
|
||||
magicWord = aWord.toUpperCase(); |
||||
setTitle("Quiz"); |
||||
|
||||
textField = new JFormattedTextField(""); |
||||
textField.setColumns(10); |
||||
textField.setFormatterFactory(new DefaultFormatterFactory(new JFormattedTextField.AbstractFormatter() { |
||||
@Override |
||||
public Object stringToValue(final String text) throws ParseException { |
||||
if (!magicWord.equals(text)) { |
||||
throw new ParseException("Invalid magic word", 0); |
||||
} |
||||
return text; |
||||
} |
||||
|
||||
@Override |
||||
public String valueToString(final Object value) { |
||||
return value == null ? "" : value.toString(); |
||||
} |
||||
})); |
||||
textField.setFocusLostBehavior(JFormattedTextField.COMMIT); |
||||
|
||||
//Create an array of the text and components to be displayed.
|
||||
String msgString1 = "What was Dr. SEUSS's real last name?"; |
||||
String msgString2 = "(The answer is \"" + magicWord + "\".)"; |
||||
Object[] array = {msgString1, msgString2, textField}; |
||||
|
||||
//Create an array specifying the number of dialog buttons
|
||||
//and their text.
|
||||
Object[] options = {btnString1, btnString2}; |
||||
|
||||
//Create the JOptionPane.
|
||||
optionPane = new JOptionPane(array, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION, |
||||
null, options, options[0]); |
||||
|
||||
//Make this dialog display it.
|
||||
setContentPane(optionPane); |
||||
|
||||
//Handle window closing correctly.
|
||||
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); |
||||
addWindowListener(new WindowAdapter() { |
||||
public void windowClosing(final WindowEvent we) { |
||||
/* |
||||
* Instead of directly closing the window, |
||||
* we're going to change the JOptionPane's |
||||
* value property. |
||||
*/ |
||||
optionPane.setValue(JOptionPane.CLOSED_OPTION); |
||||
} |
||||
}); |
||||
|
||||
//Ensure the text field always gets the first focus.
|
||||
addComponentListener(new ComponentAdapter() { |
||||
public void componentShown(final ComponentEvent ce) { |
||||
textField.requestFocusInWindow(); |
||||
} |
||||
}); |
||||
|
||||
//Register an event handler that puts the text into the option pane.
|
||||
textField.addActionListener(this); |
||||
|
||||
//Register an event handler that reacts to option pane state changes.
|
||||
optionPane.addPropertyChangeListener(this); |
||||
} |
||||
|
||||
/** |
||||
* Returns null if the typed string was invalid; |
||||
* otherwise, returns the string as the user entered it. |
||||
*/ |
||||
public String getValidatedText() { |
||||
return typedText; |
||||
} |
||||
|
||||
/** |
||||
* This method handles events for the text field. |
||||
*/ |
||||
public void actionPerformed(final ActionEvent e) { |
||||
optionPane.setValue(btnString1); |
||||
} |
||||
|
||||
/** |
||||
* This method reacts to state changes in the option pane. |
||||
*/ |
||||
public void propertyChange(final PropertyChangeEvent e) { |
||||
String prop = e.getPropertyName(); |
||||
|
||||
if (isVisible() |
||||
&& (e.getSource() == optionPane) |
||||
&& (JOptionPane.VALUE_PROPERTY.equals(prop) || |
||||
JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) { |
||||
Object value = optionPane.getValue(); |
||||
|
||||
if (value == JOptionPane.UNINITIALIZED_VALUE) { |
||||
//ignore reset
|
||||
return; |
||||
} |
||||
|
||||
//Reset the JOptionPane's value.
|
||||
//If you don't do this, then if the user
|
||||
//presses the same button next time, no
|
||||
//property change event will be fired.
|
||||
optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE); |
||||
|
||||
if (btnString1.equals(value)) { |
||||
typedText = textField.getText(); |
||||
String ucText = typedText.toUpperCase(); |
||||
if (magicWord.equals(ucText)) { |
||||
//we're done; clear and dismiss the dialog
|
||||
clearAndHide(); |
||||
} else { |
||||
//text was invalid
|
||||
textField.selectAll(); |
||||
JOptionPane.showMessageDialog(CustomDialog.this, |
||||
"Sorry, \"" + typedText + "\" " + "isn't a valid response.\n" |
||||
+ "Please enter " + magicWord + ".", |
||||
"Try again", JOptionPane.ERROR_MESSAGE); |
||||
typedText = null; |
||||
textField.requestFocusInWindow(); |
||||
} |
||||
} else { //user closed dialog or clicked cancel
|
||||
dd.setLabel("It's OK. We won't force you to type " + magicWord + "."); |
||||
typedText = null; |
||||
clearAndHide(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This method clears the dialog and hides it. |
||||
*/ |
||||
public void clearAndHide() { |
||||
textField.setText(null); |
||||
setVisible(false); |
||||
} |
||||
} |
@ -0,0 +1,587 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2019 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all |
||||
* copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
* SOFTWARE. |
||||
*/ |
||||
|
||||
package dialog; |
||||
|
||||
import com.weis.darklaf.LafManager; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.border.Border; |
||||
import java.awt.*; |
||||
import java.awt.event.WindowAdapter; |
||||
import java.awt.event.WindowEvent; |
||||
import java.util.Objects; |
||||
|
||||
/* |
||||
* DialogDemo.java requires these files: |
||||
* CustomDialog.java |
||||
* images/middle.gif |
||||
*/ |
||||
public class DialogDemo extends JPanel { |
||||
private JLabel label; |
||||
private ImageIcon icon = createImageIcon("images/middle.gif"); |
||||
private JFrame frame; |
||||
private String simpleDialogDesc = "Some simple message dialogs"; |
||||
private String iconDesc = "A JOptionPane has its choice of icons"; |
||||
private String moreDialogDesc = "Some more dialogs"; |
||||
private CustomDialog customDialog; |
||||
|
||||
/** |
||||
* Creates the GUI shown inside the frame's content pane. |
||||
*/ |
||||
public DialogDemo(final JFrame frame) { |
||||
super(new BorderLayout()); |
||||
this.frame = frame; |
||||
customDialog = new CustomDialog(frame, "geisel", this); |
||||
customDialog.pack(); |
||||
|
||||
//Create the components.
|
||||
JPanel frequentPanel = createSimpleDialogBox(); |
||||
JPanel featurePanel = createFeatureDialogBox(); |
||||
JPanel iconPanel = createIconDialogBox(); |
||||
label = new JLabel("Click the \"Show it!\" button" |
||||
+ " to bring up the selected dialog.", |
||||
JLabel.CENTER); |
||||
|
||||
//Lay them out.
|
||||
Border padding = BorderFactory.createEmptyBorder(20, 20, 5, 20); |
||||
frequentPanel.setBorder(padding); |
||||
featurePanel.setBorder(padding); |
||||
iconPanel.setBorder(padding); |
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane(); |
||||
tabbedPane.addTab("Simple Modal Dialogs", null, |
||||
frequentPanel, |
||||
simpleDialogDesc); //tooltip text
|
||||
tabbedPane.addTab("More Dialogs", null, |
||||
featurePanel, |
||||
moreDialogDesc); //tooltip text
|
||||
tabbedPane.addTab("Dialog Icons", null, |
||||
iconPanel, |
||||
iconDesc); //tooltip text
|
||||
|
||||
add(tabbedPane, BorderLayout.CENTER); |
||||
add(label, BorderLayout.PAGE_END); |
||||
label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
||||
} |
||||
|
||||
/** |
||||
* Creates the panel shown by the first tab. |
||||
*/ |
||||
private JPanel createSimpleDialogBox() { |
||||
final int numButtons = 4; |
||||
JRadioButton[] radioButtons = new JRadioButton[numButtons]; |
||||
final ButtonGroup group = new ButtonGroup(); |
||||
|
||||
JButton showItButton = null; |
||||
|
||||
final String defaultMessageCommand = "default"; |
||||
final String yesNoCommand = "yesno"; |
||||
final String yeahNahCommand = "yeahnah"; |
||||
final String yncCommand = "ync"; |
||||
|
||||
radioButtons[0] = new JRadioButton("OK (in the L&F's words)"); |
||||
radioButtons[0].setActionCommand(defaultMessageCommand); |
||||
|
||||
radioButtons[1] = new JRadioButton("Yes/No (in the L&F's words)"); |
||||
radioButtons[1].setActionCommand(yesNoCommand); |
||||
|
||||
radioButtons[2] = new JRadioButton("Yes/No " |
||||
+ "(in the programmer's words)"); |
||||
radioButtons[2].setActionCommand(yeahNahCommand); |
||||
|
||||
radioButtons[3] = new JRadioButton("Yes/No/Cancel " |
||||
+ "(in the programmer's words)"); |
||||
radioButtons[3].setActionCommand(yncCommand); |
||||
|
||||
for (int i = 0; i < numButtons; i++) { |
||||
group.add(radioButtons[i]); |
||||
} |
||||
radioButtons[0].setSelected(true); |
||||
|
||||
showItButton = new JButton("Show it!"); |
||||
showItButton.addActionListener(e -> { |
||||
String command = group.getSelection().getActionCommand(); |
||||
|
||||
//ok dialog
|
||||
if (Objects.equals(command, defaultMessageCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green."); |
||||
|
||||
//yes/no dialog
|
||||
} else if (Objects.equals(command, yesNoCommand)) { |
||||
int n = JOptionPane.showConfirmDialog( |
||||
frame, "Would you like green eggs and ham?", |
||||
"An Inane Question", |
||||
JOptionPane.YES_NO_OPTION); |
||||
if (n == JOptionPane.YES_OPTION) { |
||||
setLabel("Ewww!"); |
||||
} else if (n == JOptionPane.NO_OPTION) { |
||||
setLabel("Me neither!"); |
||||
} else { |
||||
setLabel("Come on -- tell me!"); |
||||
} |
||||
|
||||
//yes/no (not in those words)
|
||||
} else if (Objects.equals(command, yeahNahCommand)) { |
||||
Object[] options = {"Yes, please", "No way!"}; |
||||
int n = JOptionPane.showOptionDialog(frame, |
||||
"Would you like green eggs and ham?", |
||||
"A Silly Question", |
||||
JOptionPane.YES_NO_OPTION, |
||||
JOptionPane.QUESTION_MESSAGE, |
||||
null, |
||||
options, |
||||
options[0]); |
||||
if (n == JOptionPane.YES_OPTION) { |
||||
setLabel("You're kidding!"); |
||||
} else if (n == JOptionPane.NO_OPTION) { |
||||
setLabel("I don't like them, either."); |
||||
} else { |
||||
setLabel("Come on -- 'fess up!"); |
||||
} |
||||
|
||||
//yes/no/cancel (not in those words)
|
||||
} else if (Objects.equals(command, yncCommand)) { |
||||
Object[] options = {"Yes, please", |
||||
"No, thanks", |
||||
"No eggs, no ham!"}; |
||||
int n = JOptionPane.showOptionDialog(frame, |
||||
"Would you like some green eggs to go " |
||||
+ "with that ham?", |
||||
"A Silly Question", |
||||
JOptionPane.YES_NO_CANCEL_OPTION, |
||||
JOptionPane.QUESTION_MESSAGE, |
||||
null, |
||||
options, |
||||
options[2]); |
||||
if (n == JOptionPane.YES_OPTION) { |
||||
setLabel("Here you go: green eggs and ham!"); |
||||
} else if (n == JOptionPane.NO_OPTION) { |
||||
setLabel("OK, just the ham, then."); |
||||
} else if (n == JOptionPane.CANCEL_OPTION) { |
||||
setLabel("Well, I'm certainly not going to eat them!"); |
||||
} else { |
||||
setLabel("Please tell me what you want!"); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
return createPane(simpleDialogDesc + ":", |
||||
radioButtons, |
||||
showItButton); |
||||
} |
||||
|
||||
/** |
||||
* Creates the panel shown by the second tab. |
||||
*/ |
||||
private JPanel createFeatureDialogBox() { |
||||
final int numButtons = 5; |
||||
JRadioButton[] radioButtons = new JRadioButton[numButtons]; |
||||
final ButtonGroup group = new ButtonGroup(); |
||||
|
||||
JButton showItButton; |
||||
|
||||
final String pickOneCommand = "pickone"; |
||||
final String textEnteredCommand = "textfield"; |
||||
final String nonAutoCommand = "nonautooption"; |
||||
final String customOptionCommand = "customoption"; |
||||
final String nonModalCommand = "nonmodal"; |
||||
|
||||
radioButtons[0] = new JRadioButton("Pick one of several choices"); |
||||
radioButtons[0].setActionCommand(pickOneCommand); |
||||
|
||||
radioButtons[1] = new JRadioButton("Enter some text"); |
||||
radioButtons[1].setActionCommand(textEnteredCommand); |
||||
|
||||
radioButtons[2] = new JRadioButton("Non-auto-closing dialog"); |
||||
radioButtons[2].setActionCommand(nonAutoCommand); |
||||
|
||||
radioButtons[3] = new JRadioButton("Input-validating dialog " |
||||
+ "(with custom message area)"); |
||||
radioButtons[3].setActionCommand(customOptionCommand); |
||||
|
||||
radioButtons[4] = new JRadioButton("Non-modal dialog"); |
||||
radioButtons[4].setActionCommand(nonModalCommand); |
||||
|
||||
for (int i = 0; i < numButtons; i++) { |
||||
group.add(radioButtons[i]); |
||||
} |
||||
radioButtons[0].setSelected(true); |
||||
|
||||
showItButton = new JButton("Show it!"); |
||||
showItButton.addActionListener(e -> { |
||||
String command = group.getSelection().getActionCommand(); |
||||
|
||||
//pick one of many
|
||||
if (Objects.equals(command, pickOneCommand)) { |
||||
Object[] possibilities = {"ham", "spam", "yam"}; |
||||
String s = (String) JOptionPane.showInputDialog( |
||||
frame, |
||||
"Complete the sentence:\n" |
||||
+ "\"Green eggs and...\"", |
||||
"Customized Dialog", |
||||
JOptionPane.PLAIN_MESSAGE, |
||||
icon, |
||||
possibilities, |
||||
"ham"); |
||||
|
||||
//If a string was returned, say so.
|
||||
if ((s != null) && (s.length() > 0)) { |
||||
setLabel("Green eggs and... " + s + "!"); |
||||
return; |
||||
} |
||||
|
||||
//If you're here, the return value was null/empty.
|
||||
setLabel("Come on, finish the sentence!"); |
||||
|
||||
//text input
|
||||
} else if (Objects.equals(command, textEnteredCommand)) { |
||||
String s = (String) JOptionPane.showInputDialog( |
||||
frame, |
||||
"Complete the sentence:\n" |
||||
+ "\"Green eggs and...\"", |
||||
"Customized Dialog", |
||||
JOptionPane.PLAIN_MESSAGE, |
||||
icon, |
||||
null, |
||||
"ham"); |
||||
|
||||
//If a string was returned, say so.
|
||||
if ((s != null) && (s.length() > 0)) { |
||||
setLabel("Green eggs and... " + s + "!"); |
||||
return; |
||||
} |
||||
|
||||
//If you're here, the return value was null/empty.
|
||||
setLabel("Come on, finish the sentence!"); |
||||
|
||||
//non-auto-closing dialog
|
||||
} else if (Objects.equals(command, nonAutoCommand)) { |
||||
final JOptionPane optionPane = new JOptionPane( |
||||
"The only way to close this dialog is by\n" |
||||
+ "pressing one of the following buttons.\n" |
||||
+ "Do you understand?", |
||||
JOptionPane.QUESTION_MESSAGE, |
||||
JOptionPane.YES_NO_OPTION); |
||||
|
||||
//You can't use pane.createDialog() because that
|
||||
//method sets up the JDialog with a property change
|
||||
//listener that automatically closes the window
|
||||
//when a button is clicked.
|
||||
final JDialog dialog = new JDialog(frame, |
||||
"Click a button", |
||||
true); |
||||
dialog.setContentPane(optionPane); |
||||
dialog.setDefaultCloseOperation( |
||||
JDialog.DO_NOTHING_ON_CLOSE); |
||||
dialog.addWindowListener(new WindowAdapter() { |
||||
public void windowClosing(final WindowEvent we) { |
||||
setLabel("Thwarted user attempt to close window."); |
||||
} |
||||
}); |
||||
optionPane.addPropertyChangeListener( |
||||
e12 -> { |
||||
String prop = e12.getPropertyName(); |
||||
|
||||
if (dialog.isVisible() |
||||
&& (e12.getSource() == optionPane) |
||||
&& (JOptionPane.VALUE_PROPERTY.equals(prop))) { |
||||
//If you were going to check something
|
||||
//before closing the window, you'd do
|
||||
//it here.
|
||||
dialog.setVisible(false); |
||||
} |
||||
}); |
||||
dialog.pack(); |
||||
dialog.setLocationRelativeTo(frame); |
||||
dialog.setVisible(true); |
||||
|
||||
int value = (Integer) optionPane.getValue(); |
||||
if (value == JOptionPane.YES_OPTION) { |
||||
setLabel("Good."); |
||||
} else if (value == JOptionPane.NO_OPTION) { |
||||
setLabel("Try using the window decorations " |
||||
+ "to close the non-auto-closing dialog. " |
||||
+ "You can't!"); |
||||
} else { |
||||
setLabel("Window unavoidably closed (ESC?)."); |
||||
} |
||||
|
||||
//non-auto-closing dialog with custom message area
|
||||
//NOTE: if you don't intend to check the input,
|
||||
//then just use showInputDialog instead.
|
||||
} else if (Objects.equals(command, customOptionCommand)) { |
||||
customDialog.setLocationRelativeTo(frame); |
||||
customDialog.setVisible(true); |
||||
|
||||
String s = customDialog.getValidatedText(); |
||||
if (s != null) { |
||||
//The text is valid.
|
||||
setLabel("Congratulations! " + "You entered \"" + s + "\"."); |
||||
} |
||||
|
||||
//non-modal dialog
|
||||
} else if (Objects.equals(command, nonModalCommand)) { |
||||
//Create the dialog.
|
||||
final JDialog dialog = new JDialog(frame, "A Non-Modal Dialog"); |
||||
|
||||
//Add contents to it. It must have a close button,
|
||||
//since some L&Fs (notably Java/Metal) don't provide one
|
||||
//in the window decorations for dialogs.
|
||||
JLabel label = new JLabel("<html><p align=center>" |
||||
+ "This is a non-modal dialog.<br>" |
||||
+ "You can have one or more of these up<br>" |
||||
+ "and still use the main window."); |
||||
label.setHorizontalAlignment(JLabel.CENTER); |
||||
label.setFont(label.getFont().deriveFont(Font.PLAIN, 14.0f)); |
||||
|
||||
JButton closeButton = new JButton("Close"); |
||||
closeButton.addActionListener(e1 -> { |
||||
dialog.setVisible(false); |
||||
dialog.dispose(); |
||||
}); |
||||
JPanel closePanel = new JPanel(); |
||||
closePanel.setLayout(new BoxLayout(closePanel, BoxLayout.LINE_AXIS)); |
||||
closePanel.add(Box.createHorizontalGlue()); |
||||
closePanel.add(closeButton); |
||||
closePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 5)); |
||||
|
||||
JPanel contentPane = new JPanel(new BorderLayout()); |
||||
contentPane.add(label, BorderLayout.CENTER); |
||||
contentPane.add(closePanel, BorderLayout.PAGE_END); |
||||
contentPane.setOpaque(true); |
||||
dialog.setContentPane(contentPane); |
||||
|
||||
//Show it.
|
||||
dialog.setSize(new Dimension(300, 150)); |
||||
dialog.setLocationRelativeTo(frame); |
||||
dialog.setVisible(true); |
||||
} |
||||
}); |
||||
|
||||
return createPane(moreDialogDesc + ":", radioButtons, showItButton); |
||||
} |
||||
|
||||
/* |
||||
* Creates the panel shown by the 3rd tab. |
||||
* These dialogs are implemented using showMessageDialog, but |
||||
* you can specify the icon (using similar code) for any other |
||||
* kind of dialog, as well. |
||||
*/ |
||||
private JPanel createIconDialogBox() { |
||||
JButton showItButton = null; |
||||
|
||||
final int numButtons = 6; |
||||
JRadioButton[] radioButtons = new JRadioButton[numButtons]; |
||||
final ButtonGroup group = new ButtonGroup(); |
||||
|
||||
final String plainCommand = "plain"; |
||||
final String infoCommand = "info"; |
||||
final String questionCommand = "question"; |
||||
final String errorCommand = "error"; |
||||
final String warningCommand = "warning"; |
||||
final String customCommand = "custom"; |
||||
|
||||
radioButtons[0] = new JRadioButton("Plain (no icon)"); |
||||
radioButtons[0].setActionCommand(plainCommand); |
||||
|
||||
radioButtons[1] = new JRadioButton("Information icon"); |
||||
radioButtons[1].setActionCommand(infoCommand); |
||||
|
||||
radioButtons[2] = new JRadioButton("Question icon"); |
||||
radioButtons[2].setActionCommand(questionCommand); |
||||
|
||||
radioButtons[3] = new JRadioButton("Error icon"); |
||||
radioButtons[3].setActionCommand(errorCommand); |
||||
|
||||
radioButtons[4] = new JRadioButton("Warning icon"); |
||||
radioButtons[4].setActionCommand(warningCommand); |
||||
|
||||
radioButtons[5] = new JRadioButton("Custom icon"); |
||||
radioButtons[5].setActionCommand(customCommand); |
||||
|
||||
for (int i = 0; i < numButtons; i++) { |
||||
group.add(radioButtons[i]); |
||||
} |
||||
radioButtons[0].setSelected(true); |
||||
|
||||
showItButton = new JButton("Show it!"); |
||||
showItButton.addActionListener(e -> { |
||||
String command = group.getSelection().getActionCommand(); |
||||
|
||||
//no icon
|
||||
if (Objects.equals(command, plainCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green.", |
||||
"A plain message", |
||||
JOptionPane.PLAIN_MESSAGE); |
||||
//information icon
|
||||
} else if (Objects.equals(command, infoCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green.", |
||||
"Inane informational dialog", |
||||
JOptionPane.INFORMATION_MESSAGE); |
||||
|
||||
//XXX: It doesn't make sense to make a question with
|
||||
//XXX: only one button.
|
||||
//XXX: See "Yes/No (but not in those words)" for a better solution.
|
||||
//question icon
|
||||
} else if (Objects.equals(command, questionCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"You shouldn't use a message dialog " |
||||
+ "(like this)\n" |
||||
+ "for a question, OK?", |
||||
"Inane question", |
||||
JOptionPane.QUESTION_MESSAGE); |
||||
//error icon
|
||||
} else if (Objects.equals(command, errorCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green.", |
||||
"Inane error", |
||||
JOptionPane.ERROR_MESSAGE); |
||||
//warning icon
|
||||
} else if (Objects.equals(command, warningCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green.", |
||||
"Inane warning", |
||||
JOptionPane.WARNING_MESSAGE); |
||||
//custom icon
|
||||
} else if (Objects.equals(command, customCommand)) { |
||||
JOptionPane.showMessageDialog(frame, |
||||
"Eggs aren't supposed to be green.", |
||||
"Inane custom dialog", |
||||
JOptionPane.INFORMATION_MESSAGE, |
||||
icon); |
||||
} |
||||
}); |
||||
|
||||
return create2ColPane(iconDesc + ":", |
||||
radioButtons, |
||||
showItButton); |
||||
} |
||||
|
||||
/** |
||||
* Sets the text displayed at the bottom of the frame. |
||||
*/ |
||||
void setLabel(final String newText) { |
||||
label.setText(newText); |
||||
} |
||||
|
||||
/** |
||||
* Used by createSimpleDialogBox and createFeatureDialogBox |
||||
* to create a pane containing a description, a single column |
||||
* of radio buttons, and the Show it! button. |
||||
*/ |
||||
private JPanel createPane(final String description, |
||||
final JRadioButton[] radioButtons, |
||||
final JButton showButton) { |
||||
|
||||
JPanel box = new JPanel(); |
||||
JLabel label = new JLabel(description); |
||||
|
||||
box.setLayout(new BoxLayout(box, BoxLayout.PAGE_AXIS)); |
||||
box.add(label); |
||||
|
||||
for (JRadioButton radioButton : radioButtons) { |
||||
box.add(radioButton); |
||||
} |
||||
|
||||
JPanel pane = new JPanel(new BorderLayout()); |
||||
pane.add(box, BorderLayout.PAGE_START); |
||||
pane.add(showButton, BorderLayout.PAGE_END); |
||||
return pane; |
||||
} |
||||
|
||||
/** |
||||
* Like createPane, but creates a pane with 2 columns of radio |
||||
* buttons. The number of buttons passed in *must* be even. |
||||
*/ |
||||
private JPanel create2ColPane(final String description, |
||||
final JRadioButton[] radioButtons, |
||||
final JButton showButton) { |
||||
JLabel label = new JLabel(description); |
||||
int numPerColumn = radioButtons.length / 2; |
||||
|
||||
JPanel grid = new JPanel(new GridLayout(0, 2)); |
||||
for (int i = 0; i < numPerColumn; i++) { |
||||
grid.add(radioButtons[i]); |
||||
grid.add(radioButtons[i + numPerColumn]); |
||||
} |
||||
|
||||
JPanel box = new JPanel(); |
||||
box.setLayout(new BoxLayout(box, BoxLayout.PAGE_AXIS)); |
||||
box.add(label); |
||||
grid.setAlignmentX(0.0f); |
||||
box.add(grid); |
||||
|
||||
JPanel pane = new JPanel(new BorderLayout()); |
||||
pane.add(box, BorderLayout.PAGE_START); |
||||
pane.add(showButton, BorderLayout.PAGE_END); |
||||
|
||||
return pane; |
||||
} |
||||
|
||||
/** |
||||
* Returns an ImageIcon, or null if the path was invalid. |
||||
*/ |
||||
private static ImageIcon createImageIcon(final String path) { |
||||
java.net.URL imgURL = DialogDemo.class.getResource(path); |
||||
if (imgURL != null) { |
||||
return new ImageIcon(imgURL); |
||||
} else { |
||||
System.err.println("Couldn't find file: " + path); |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public static void main(final String[] args) { |
||||
//Schedule a job for the event-dispatching thread:
|
||||
//creating and showing this application's GUI.
|
||||
LafManager.install(); |
||||
javax.swing.SwingUtilities.invokeLater(DialogDemo::createAndShowGUI); |
||||
} |
||||
|
||||
/** |
||||
* Create the GUI and show it. For thread safety, |
||||
* this method should be invoked from the |
||||
* event-dispatching thread. |
||||
*/ |
||||
private static void createAndShowGUI() { |
||||
//Create and set up the window.
|
||||
JFrame frame = new JFrame("DialogDemo"); |
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
||||
|
||||
//Create and set up the content pane.
|
||||
DialogDemo newContentPane = new DialogDemo(frame); |
||||
newContentPane.setOpaque(true); //content panes must be opaque
|
||||
frame.setContentPane(newContentPane); |
||||
|
||||
//Display the window.
|
||||
frame.pack(); |
||||
frame.setLocationRelativeTo(null); |
||||
frame.setVisible(true); |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 235 B |
@ -0,0 +1,203 @@
|
||||
/* |
||||
* MIT License |
||||
* |
||||
* Copyright (c) 2019 Jannis Weis |
||||
* |
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
* of this software and associated documentation files (the "Software"), to deal |
||||
* in the Software without restriction, including without limitation the rights |
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
* copies of the Software, and to permit persons to whom the Software is |
||||
* furnished to do so, subject to the following conditions: |
||||
* |
||||
* The above copyright notice and this permission notice shall be included in all |
||||
* copies or substantial portions of the Software. |
||||
* |
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
* SOFTWARE. |
||||
*/ |
||||
|
||||
package formattedTextField; |
||||
|
||||
import com.weis.darklaf.LafManager; |
||||
|
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.beans.PropertyChangeEvent; |
||||
import java.beans.PropertyChangeListener; |
||||
import java.text.NumberFormat; |
||||
|
||||
/** |
||||
* FormattedTextFieldDemo.java requires no other files. |
||||
* <p> |
||||
* It implements a mortgage calculator that uses four |
||||
* JFormattedTextFields. |
||||
*/ |
||||
public class FormattedTextFieldDemo extends JPanel |
||||
implements PropertyChangeListener { |
||||
//Strings for the labels
|
||||
private static String amountString = "Loan Amount: "; |
||||
private static String rateString = "APR (%): "; |
||||
private static String numPeriodsString = "Years: "; |
||||
private static String paymentString = "Monthly Payment: "; |
||||
//Values for the fields
|
||||
private double amount = 100000; |
||||
private double rate = 7.5; //7.5%
|
||||
private int numPeriods = 30; |
||||
//Labels to identify the fields
|
||||
private JLabel amountLabel; |
||||
private JLabel rateLabel; |
||||
private JLabel numPeriodsLabel; |
||||
private JLabel paymentLabel; |
||||
//Fields for data entry
|
||||
private JFormattedTextField amountField; |
||||
private JFormattedTextField rateField; |
||||
private JFormattedTextField numPeriodsField; |
||||
private JFormattedTextField paymentField; |
||||
|
||||
//Formats to format and parse numbers
|
||||
private NumberFormat amountFormat; |
||||
private NumberFormat percentFormat; |
||||
private NumberFormat paymentFormat; |
||||
|
||||
public FormattedTextFieldDemo() { |
||||
super(new BorderLayout()); |
||||
setUpFormats(); |
||||
double payment = computePayment(amount, |
||||
rate, |
||||
numPeriods); |
||||
|
||||
//Create the labels.
|
||||
amountLabel = new JLabel(amountString); |
||||
rateLabel = new JLabel(rateString); |
||||
numPeriodsLabel = new JLabel(numPeriodsString); |
||||
paymentLabel = new JLabel(paymentString); |
||||
|
||||
//Create the text fields and set them up.
|
||||
amountField = new JFormattedTextField(amountFormat); |
||||
amountField.setValue(new Double(amount)); |
||||
amountField.setColumns(10); |
||||
amountField.addPropertyChangeListener("value", this); |
||||
|
||||
rateField = new JFormattedTextField(percentFormat); |
||||
rateField.setValue(new Double(rate)); |
||||
rateField.setColumns(10); |
||||
rateField.addPropertyChangeListener("value", this); |
||||
|
||||
numPeriodsField = new JFormattedTextField(); |
||||
numPeriodsField.setValue(new Integer(numPeriods)); |
||||
numPeriodsField.setColumns(10); |
||||
numPeriodsField.addPropertyChangeListener("value", this); |
||||
|
||||
paymentField = new JFormattedTextField(paymentFormat); |
||||
paymentField.setValue(new Double(payment)); |
||||
paymentField.setColumns(10); |
||||
paymentField.setEditable(false); |
||||
paymentField.setForeground(Color.red); |
||||
|
||||
//Tell accessibility tools about label/textfield pairs.
|
||||
amountLabel.setLabelFor(amountField); |
||||
rateLabel.setLabelFor(rateField); |
||||
numPeriodsLabel.setLabelFor(numPeriodsField); |
||||
paymentLabel.setLabelFor(paymentField); |
||||
|
||||
//Lay out the labels in a panel.
|
||||
JPanel labelPane = new JPanel(new GridLayout(0, 1)); |
||||
labelPane.add(amountLabel); |
||||
labelPane.add(rateLabel); |
||||
labelPane.add(numPeriodsLabel); |
||||
labelPane.add(paymentLabel); |
||||
|
||||
//Layout the text fields in a panel.
|
||||
JPanel fieldPane = new JPanel(new GridLayout(0, 1)); |
||||
fieldPane.add(amountField); |
||||
fieldPane.add(rateField); |
||||
fieldPane.add(numPeriodsField); |
||||
fieldPane.add(paymentField); |
||||
|
||||
//Put the panels in this panel, labels on left,
|
||||
//text fields on right.
|
||||
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); |
||||
add(labelPane, BorderLayout.CENTER); |
||||
add(fieldPane, BorderLayout.LINE_END); |
||||
} |
||||
|
||||
//Create and set up number formats. These objects also
|
||||
//parse numbers input by user.
|
||||
private void setUpFormats() { |
||||
amountFormat = NumberFormat.getNumberInstance(); |
||||
|
||||
percentFormat = NumberFormat.getNumberInstance(); |
||||
percentFormat.setMinimumFractionDigits(3); |
||||
|
||||
paymentFormat = NumberFormat.getCurrencyInstance(); |
||||
} |
||||
|
||||
//Compute the monthly payment based on the loan amount,
|
||||
//APR, and length of loan.
|
||||
private double computePayment(final double loanAmt, final double rate, int numPeriods) { |
||||
double I, partial1, denominator, answer; |
||||
|
||||
numPeriods *= 12; //get number of months
|
||||
if (rate > 0.01) { |
||||
I = rate / 100.0 / 12.0; //get monthly rate from annual
|
||||
partial1 = Math.pow((1 + I), (0.0 - numPeriods)); |
||||
denominator = (1 - partial1) / I; |
||||
} else { //rate ~= 0
|
||||
denominator = numPeriods; |
||||
} |
||||
|
||||
answer = (-1 * loanAmt) / denominator; |
||||
return answer; |
||||
} |
||||
|
||||
public static void main(final String[] args) { |
||||
//Schedule a job for the event dispatch thread:
|
||||
//creating and showing this application's GUI.
|
||||
SwingUtilities.invokeLater(() -> { |
||||
//Turn off metal's use of bold fonts
|
||||
LafManager.install(); |
||||
createAndShowGUI(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Create the GUI and show it. For thread safety, |
||||
* this method should be invoked from the |
||||
* event dispatch thread. |
||||
*/ |
||||
private static void createAndShowGUI() { |
||||
//Create and set up the window.
|
||||
JFrame frame = new JFrame("FormattedTextFieldDemo"); |
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
||||
|
||||
//Add contents to the window.
|
||||
frame.add(new FormattedTextFieldDemo()); |
||||
|
||||
//Display the window.
|
||||
frame.pack(); |
||||
frame.setVisible(true); |
||||
} |
||||
|
||||
/** |
||||
* Called when a field's "value" property changes. |
||||
*/ |
||||
public void propertyChange(final PropertyChangeEvent e) { |
||||
Object source = e.getSource(); |
||||
if (source == amountField) { |
||||
amount = ((Number) amountField.getValue()).doubleValue(); |
||||
} else if (source == rateField) { |
||||
rate = ((Number) rateField.getValue()).doubleValue(); |
||||
} else if (source == numPeriodsField) { |
||||
numPeriods = ((Number) numPeriodsField.getValue()).intValue(); |
||||
} |
||||
|
||||
double payment = computePayment(amount, rate, numPeriods); |
||||
paymentField.setValue(new Double(payment)); |
||||
} |
||||
} |
After Width: | Height: | Size: 172 B |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 172 B |
Loading…
Reference in new issue