JXDatePicker make arrows in the JXMonthView bigger - java

I want to use this JXDatePicker component in a application that will work on a touch display. Because the default component is small, all the dates and the buttons are hard to click using a bad touch screen I wanted to make them bigger. So far I successfully made the result text field bigger (the one showing the selected date, by changing the font), make the pop-up bigger (the JXMonthView, also by changing its font), change the picture of the JXDatePicker with a bigger image, set the default date to be the current date, set the date format, etc. This is my code:
private void touch_screen_datepicker(JXDatePicker date_picker) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
JXMonthView monthView = date_picker.getMonthView();
date_picker.setDate(new Date());
date_picker.setFont(new Font(Font.DIALOG, Font.PLAIN, 50));
JButton btn_pick = (JButton) date_picker.getComponent(1);
btn_pick.setBackground(new Color(66, 147, 223));
Image image = toolkit.getImage("/home/adrrian/Image/calendar/" + "calendar image 4.png"); //Земање на сликата за мк знаме
ImageIcon icon = new ImageIcon(image); //Правење на икона
btn_pick.setIcon(icon); //Поставување на иконата
SimpleDateFormat longFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat shortFormat = new SimpleDateFormat("yy-MM-dd");
Date startDate = new Date(0);//01.01.1970
shortFormat.set2DigitYearStart(startDate);
DatePickerFormatter formatter = new DatePickerFormatter(
// invers sequence for parsing to satisfy the year parsing rules
new DateFormat[]{shortFormat, longFormat}) {
#Override
public String valueToString(Object value) throws ParseException {
if (value == null) {
return null;
}
return getFormats()[1].format(value);
}
};
DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
date_picker.getEditor().setFormatterFactory(factory);
monthView.setFont(new Font(Font.DIALOG, Font.PLAIN, 50));
monthView.setFirstDayOfWeek(Calendar.MONDAY);
}
and this is an image of my final work:
My main problem is how to make the arrow that are changing the months (for example if I go back from this image to show September). I tried listing all of the components, like I did for the button, but still I didn't found anything. Also for better GUI I like to find that dark blue color (where the month is displayed), to make my button the same.
Hope someone can help me. Thanks in advance.
Toolkit toolkit = Toolkit.getDefaultToolkit();
JXMonthView monthView = date_picker.getMonthView();
/*EDITED*/
//1
date_picker.putClientProperty("JComponent.sizeVariant", "large");
monthView.putClientProperty("JComponent.sizeVariant", "large");
//2
date_picker.putClientProperty("JXComponent.sizeVariant", "large");
monthView.putClientProperty("JXComponent.sizeVariant", "large");
//3
date_picker.putClientProperty("JXDatePicker.sizeVariant", "large");
monthView.putClientProperty("JXMonthView.sizeVariant", "large");
//
date_picker.putClientProperty("JDatePicker.sizeVariant", "large");
monthView.putClientProperty("JMonthView.sizeVariant", "large");
SwingUtilities.updateComponentTreeUI(this);
SwingUtilities.updateComponentTreeUI(date_picker);
SwingUtilities.updateComponentTreeUI(monthView);
date_picker.updateUI();
monthView.updateUI();
/*EDITED*/
As #Vighanesh Gursale suggested I insterdet this lines and also did the frame.pack() before setVisible(true), but nothing changes.

I have made some code using nimbus look and feel, i know it is not exact that you want but it is pretty much helpful. Check this code. To perform same you need to find the key of your next and previous buttons key in my case it is Button.margin. Try to use the same key in your code if you are lucky it would work.
import javax.swing.*;
import java.awt.*;
public class Demo {
JFrame frame = new JFrame("");
JButton btn = new JButton("Example");
public Demo() {
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(btn);
frame.setVisible(true);
}
public static void main(String[] args) {
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
Insets insets = new Insets(50, 20, 50, 20); //change the size of button
UIManager.put("Button.margin", insets);
}
catch(Exception e)
{
e.printStackTrace();
}
Demo d = new Demo();
}
}
Also keep in mind to use default look and feel or any other look and feel.

This question is quite old but for everyone who is looking how it can be done
UIManager.put("JXMonthView.monthDownFileName", <PATH_TO_IMAGE>);
UIManager.put("JXMonthView.monthUpFileName", <PATH_TO_IMAGE>);
monthDownFileName refers to previous month
monthUpFileName refers to next month
this will change the image with other of your choice (and size)

Related

Java how do I access text field

I'm relatively new to programming. Hoping someone can help. I have a button that creates a series of labels and text boxes within a frame once the user enters a number. I'm having trouble access the text boxes once they are created. Can someone point me in the right direction. Code snips below. Thanks.
method to create a label and text box.
public JTextField createPrizePanels(){
JLabel prizePanel = new JLabel("Enter Prize Here", SwingConstants.CENTER);
prizePanel.setVerticalAlignment(SwingConstants.TOP);
prizePanel.setFont(new Font("Arial", Font.BOLD, 14));
prizePanel.setForeground(Color.BLUE);
Border border = BorderFactory.createLineBorder(Color.GRAY, 1);
prizePanel.setBorder(border);
prizePanel.setOpaque(true);
prizePanel.setBackground(Color.LIGHT_GRAY);
prizePanel.setBounds(setBoundsX, setBoundsY, 120, 60);
prizeTextBox = new JTextField(50);
prizeTextBox.setBounds(setBoundsX + 5, setBoundsY + 20, 110, 30);
prizeTextBox.setFont(new Font("Arial", Font.BOLD, 12));
prizeTextBox.setOpaque(true);
prizeTextBox.setBackground(Color.WHITE);
prizeTextBox.setForeground(Color.BLACK);
prizeTextBox.setText("No Prize");
prizeTextBox.setHorizontalAlignment(JTextField.CENTER);
lp.add(prizePanel);
lp.add(prizeTextBox);
return prizeTextBox;
}
code that creates multiple text boxes bases on input from user.
JButton numberOfBallonsButton = new JButton("Set");
numberOfBallonsButton.setBounds(360,160,95, 0x1e);
numberOfBallonsButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
numberOfBallons = Integer.parseInt(numberOfBallonsTextBox.getText());
System.out.println(numberOfBallons);
lp.remove(numberOfBallonsButton);
for(int i = 0; i < numberOfBallons; i++ ){
createPrizePanels();
setBoundsX = setBoundsX +125;
if(setBoundsX > 450){
setBoundsX = 120;
setBoundsY = setBoundsY + 65;
}
}
lp.add(startGameButton);
}
});
Up to this point it works fine. However, the user needs to enter text into each text box and press another button. I'm not sure how to access each text field. Thanks in advance.
You are using local fields.you can create global field and the return value of createPrizePanels() is never used and for your case you don't know number of created textfield so you can use List as global field and when you create textfield add it to the list so you access it later from anywhere

Show only months and years with JDatePicker

I am trying to use JDatePicker to display a calendar. However, I only want to display months and years, not the days.
I tried poking around the model and JDatePickerImpl objects, without luck.
Here is the code I have to show the JDatePicker, from documentation:
UtilCalendarModel model = new UtilCalendarModel();
Properties p = new Properties();
p.put("text.today", "Today");
p.put("text.month", "Month");
p.put("text.year", "Year");
JDatePanelImpl datePanel = new JDatePanelImpl(model, p);
JDatePickerImpl datePicker = new JDatePickerImpl(datePanel, new DateComponentFormatter());
Thanks in advance!
Note: Here is an image of what I mean.
After looking at the code from the JDatePicker project, I think this is possible by making a custom version of the JDatePanelImpl class (and perhaps some other classes). The functionality you want is not yet configurable in the standard classes, but it could be implemented as an enhancement and sent to the JDatePicker developers as a proposal (pull request).
Just to be sure of what you need for your application: you want to use a calendar similar to the example below? The user could change the selected month & year by clicking the next/previous month buttons, selecting a month from the month popup menu, or selecting a different year (using the year spinner):
Edit: added example with adapted versions of JDatePicker classes
I have added a modified example of your code and two adapted versions of JDatePicker classes. The normal component closes the popup when the user clicks a specific day, which is not possible in this case (since the days are hidden). I have added a small OK button to make it possible to close the date picker (see screenshot above). This is clearly a proof of concept only; the code really needs more work.
(Note: when I tried to add the two modified classes, my answer became to big. Therefore I forked the JDatePicker project on GitHub, rewrote the customizations from JDatePicker version 1.3.4 to version 1.3.4.1, and added links for these two files instead of all the code.)
// ExampleDatePickerWithoutDay class:
import java.text.*;
import javax.swing.*;
import org.jdatepicker.*;
public class ExampleDatePickerWithoutDay {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ExampleDatePickerWithoutDay().createAndShowGui();
}
});
}
private void createAndShowGui() {
JFrame frame = new JFrame("Stack Overflow");
frame.setBounds(100, 100, 800, 200);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
// Set two date formats and a text label.
DateFormat dateFormat = new SimpleDateFormat("MMMM yyyy");
ComponentFormatDefaults.Key formatKey;
formatKey = ComponentFormatDefaults.Key.SELECTED_DATE_FIELD;
ComponentFormatDefaults.getInstance().setFormat(formatKey, dateFormat);
formatKey = ComponentFormatDefaults.Key.TODAY_SELECTOR;
ComponentFormatDefaults.getInstance().setFormat(formatKey, dateFormat);
ComponentTextDefaults.Key textKey = ComponentTextDefaults.Key.TODAY;
ComponentTextDefaults.getInstance().setText(textKey, "Current month");
// Create the date picker.
UtilCalendarModel calendarModel = new UtilCalendarModel();
CustomDatePanel datePanel = new CustomDatePanel(calendarModel);
CustomDatePicker datePicker = new CustomDatePicker(datePanel);
panel.add(datePicker);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}
CustomDatePanel class: CustomDatePanel.java (on GitHub)
CustomDatePicker class: CustomDatePicker.java (on GitHub)

SwingX - personalize JXDatePicker

I want to personalize the JXDatePicker. More specifically I want to create an own own action button on a an own position. I tried to extract the included JButton but when I try to add it to any JPanel it only adds empty space.
JXDatePicker fDate = new JXDatePicker(new Date());
fDate.getEditor().setBorder(null);
fDate.getEditor().setEditable(false);
JButton eDate = (JButton) fDate.getComponent(1);
fDate.remove(eDate);
I don't think this approach would work anyway, but I don't know any better at the moment.
Any suggestions?
found a working solution, migt be not the cleanest way:
JXDatePicker fDate = new JXDatePicker(new Date());
//edit the Textfield
fDate.getEditor().setBorder(null);
fDate.getEditor().setEditable(false);
//edit the Button
JButton dateBtn= (JButton) fDate.getComponent(1);
Image editImage =Toolkit.getDefaultToolkit().getImage(getClass().getResource("/toolbarButtonGraphics/general/Edit16.gif"));
dateBtn.remove(eDate);
dateBtn.setIcon(new ImageIcon(editImage));
dateBtn.setFocusPainted(false);
dateBtn.setMargin(new Insets(0, 0, 0, 0));
dateBtn.setContentAreaFilled(false);
dateBtn.setBorderPainted(false);
dateBtn.setOpaque(false);
I added the dateBtn somewhere else in my view.
((JButton) startDatePicker.getComponent(1)).setIcon(new ImageIcon(((new ImageIcon(getClass().getResource("/images/calendar.png"))).getImage()).getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));

BorderLayout delay issues

After a very long couple of days I have determined that there is a delay when displaying text very quickly in a text area if that text area is in a border layout. My question is, why does the following code take 10-20 times longer to execute using border layout than without (comment out one of the two methods either addWithBorderLayout or addWithoutBorderLayout) AND is there a way to use the border layout without this delay? (The problem exists with or without the SwingUtilities invokeLater() method.)
import java.awt.BorderLayout;
import java.awt.Label;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JDesktopPane;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class Driver
{
public static void main(String args[])
{
System.out.println("JEditPane Test");
//window to display the plyed back text
JFrame mainFrame = new JFrame("Main Frame");
//holds some text to be played back
final JEditorPane editPane1 = new JEditorPane();
final JEditorPane editPane2 = new JEditorPane();
//desktop pane to hold docs
JDesktopPane desktopPane = new JDesktopPane();
//create an internal frame
JInternalFrame internalFrame1 = new JInternalFrame("Test Doc 1", true, true, true, true);
internalFrame1.setContentPane(new JScrollPane(editPane1));
internalFrame1.setSize(400, 400);
internalFrame1.setVisible(true);
internalFrame1.setLocation(0, 0);
JInternalFrame internalFrame2 = new JInternalFrame("Test Doc 2", true, true, true, true);
internalFrame2.setContentPane(new JScrollPane(editPane2));
internalFrame2.setSize(400, 400);
internalFrame2.setVisible(true);
internalFrame2.setLocation(400, 0);
//add it to the desktop
desktopPane.add(internalFrame1);
desktopPane.add(internalFrame2);
//map of editor panes
final Map < String, JEditorPane > mapOfPanes = new HashMap < String, JEditorPane >();
mapOfPanes.put("1", editPane1);
mapOfPanes.put("2", editPane2);
//COMMENT ONE OF THESE TWO OUT!!!
addWithBorderLayout(mainFrame, desktopPane);
//addWithoutBorderLayout(mainFrame, desktopPane);
//for closing
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//set the size and location of the window
mainFrame.setSize(800,500);
mainFrame.setLocation(100, 100);
//make the window visible
mainFrame.setVisible(true);
//create some text to display
StringBuilder builder = new StringBuilder();
builder.append("This is a rather long string of text. ");
//build up a good amount of text
for(int i = 0;i < 5;i++)
{
//copy it a few times
builder.append(builder.toString());
}
//get the string
final String longStringOfText = builder.toString();
//create a thread to call setText on the editor pane
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
//for gathering stats
int sum = 0;
int numberOfCharsToPrintFromString = 0;
Date prev = new Date();
Date current = new Date();
System.out.println("Num Panes: " + mapOfPanes.size());
//for each pane
for(JEditorPane pane : mapOfPanes.values())
{
//to help in printing subsections of the big string
numberOfCharsToPrintFromString = 0;
while(numberOfCharsToPrintFromString < longStringOfText.length())
{
//wait a short amount of time
try{Thread.sleep(1);}catch(Exception e){}
//grab sections of the long string
String text = longStringOfText.substring(0, numberOfCharsToPrintFromString);
//set the text of the pane
pane.setText(text);
//stats
numberOfCharsToPrintFromString++;
long diff = current.getTime() - prev.getTime();
sum = sum + (int)diff;
prev = current;
current = new Date();
}
}
System.out.println("Average time in between events: " + ((double)sum/(double)numberOfCharsToPrintFromString));
}
});
thread.start();
}
private static void addWithoutBorderLayout(JFrame mainFrame, JDesktopPane desktopPane)
{
mainFrame.add(desktopPane);
}
private static void addWithBorderLayout(JFrame mainFrame, JDesktopPane desktopPane)
{
mainFrame.setLayout(new BorderLayout());
mainFrame.add(new Label("Top Panel"), BorderLayout.NORTH);
mainFrame.add(desktopPane, BorderLayout.CENTER);
mainFrame.add(new Label("Bottom Panel"), BorderLayout.SOUTH);
}
}
On Mac OS X 10.5.8 using Java version 1.6, I see a comparable disparity unless I set apple.awt.graphics.UseQuartz at the beginning of main(). Here is a related example that affects font rendering quality rather than execution time.
if (System.getProperty("os.name").startsWith("Mac OS X")) {
System.setProperty("apple.awt.graphics.UseQuartz", "true");
}
I use JDK6_17 on XP with an older computer and don't notice the difference you experience. My timings where betweenn 20-22 in both cases.
I then changed the sleep time to 10ms and the timings are remarkably similiar.
For the default layout:
Average time in between events: 31.236842105263158
Average time in between events: 31.236842105263158
Average time in between events: 31.236842105263158
For the Border layout:
Average time in between events: 31.236842105263158
Average time in between events: 31.23766447368421
Average time in between events: 31.236842105263158
In fact I can't believe they are identical in 5 of 6 cases.
By default the content pane of a JFrame does use a BorderLayout. So when you add components to the frame all you need to do is:
frame.add(topComponent, BorderLayout.NORTH);
frame.add(centerComponent);
frame.add(bottomComponent, BorderLayout.SOUTH);
and the frame will add the components to the content pane at the proper location.
Why are you changing the layout of the frame, instead of the content pane. Normally you would only ever change the layout of the content pane. The root pane of the frame is use to hold the menu bar and the content pane. So maybe you change the default layout manager of the entire frame you are causing some problems?

How do I easily edit the style of the selected text in a JTextPane?

How do I easily edit the style of the selected text in a JTextPane? There doesn't seem to be many resources on this. Even if you can direct me to a good resource on this, I'd greatly appreciate it.
Also, how do I get the current style of the selected text? I tried styledDoc.getLogicalStyle(textPane.getSelectionStart()); but it doesn't seem to be working.
Here's a code snippet to insert a formatted "Hello World!" string in a JEditorPane:
Document doc = yourEditorPane.getDocument();
StyleContext sc = new StyleContext();
Style style = sc.addStyle("yourStyle", null);
Font font = new Font("Arial", Font.BOLD, 18);
StyleConstants.setForeground(style, Color.RED);
StyleConstants.setFontFamily(style, font.getFamily());
StyleConstants.setBold(style, true);
doc.insertString(doc.getLength(), "Hello World!", style);
Take a look at the following code in this pastebin:
http://pbin.oogly.co.uk/listings/viewlistingdetail/d6fe483a52c52aa951ca15762ed3d3
The example is from here:
http://www.java2s.com/Code/Java/Swing-JFC/JTextPaneStylesExample3.htm
It looks like you can change the style using the following in an action listener:
final Style boldStyle = sc.addStyle("MainStyle", defaultStyle);
StyleConstants.setBold(boldStyle, true);
doc.setCharacterAttributes(0, 10, boldStyle, true);
It sets the style of the text between the given offset and length to a specific style.
See the full pastebin for more details. That should fix your problem though.
The easiest way to manipulate text panels is using editor kits and their associated actions. You can find a demo of this in the JDK samples (under jdk\demo\jfc\Stylepad).
Sample code that installs a StyledEditorKit and uses a FontSizeAction to manipulate the text:
public static void main(String[] args) {
// create a rich text pane
JTextPane textPane = new JTextPane();
JScrollPane scrollPane = new JScrollPane(textPane,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// install the editor kit
StyledEditorKit editorKit = new StyledEditorKit();
textPane.setEditorKit(editorKit);
// build the menu
JMenu fontMenu = new JMenu("Font Size");
for (int i = 48; i >= 8; i -= 10) {
JMenuItem menuItem = new JMenuItem("" + i);
// add an action
menuItem
.addActionListener(new StyledEditorKit.FontSizeAction(
"myaction-" + i, i));
fontMenu.add(menuItem);
}
JMenuBar menuBar = new JMenuBar();
menuBar.add(fontMenu);
// show in a frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.setJMenuBar(menuBar);
frame.setContentPane(scrollPane);
frame.setVisible(true);
}
(Tip: if you want to use a FontFamilyAction, have a look at GraphicsEnvironment.getAvailableFontFamilyNames() and logical font family names.)
I'd recommend taking a look at Sun's Java Tutorial about editor panes.
Ok, wow. Hard question. So I have not found a way to get the style of a given character. You can, however, get the MutableAttributeSet for a given character and then test to see if the style is in that attribute set.
Style s; //your style
Element run = styledDocument.getCharacterElement(
textPane.getSelectionStart() );
MutableAttributeSet curAttr =
( MutableAttributeSet )run.getAttributes();
boolean containsIt = curAttr.containsAttributes( s );
One problem with getting the Style for a range of characters is that there may be more than one style applied to that range (example: you may select text where some is bold and some is not).
To update the selected text you can:
Style s; //your style
JTextPane textPane; //your textpane
textPane.setCharacterAttributes( s, false );
Oh, and it appears that the function getLogicalStyle doesn't work because it's returning the default style (or maybe just the style) for the paragraph that contains p, rather than the the style of the character at p.

Categories

Resources