JFileChooser with additional JCheckBox for setting the file opening method - java

I am using JFileChooser as a component for selecting files in this code.
I need one additional input from the user to trigger the way how the file shall be opened. In my use case if it shall be read to the RAM entirely or not.
I know I can ask user elsewhere but the best would be if I can add JCheckBox to the JFileChooser dialog. I want to achieve something as on the picture.
How I can do that and how I read the status of user input?

I figured out the simplest is to utilize the mechanism that is intended for image thumbnails of selected files. By providing so called Accessory Component, which must be a child class of JComponent, through calling JFileChooser.setAccessory you can obtain a space to the right of file selecting rectangle.
Including minimal example:
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Open DEN file...");
fc.setAccessory(new CheckBoxAccessory());
int returnVal = fc.showOpenDialog(frame);
CheckBoxAccessory cba = (CheckBoxAccessory)fc.getAccessory();
boolean useVirtualStack = cba.isBoxSelected();
JOptionPane.showMessageDialog(null, String.format("selected=%b", useVirtualStack));
where the class CheckBoxAccessory looks as follows
public class CheckBoxAccessory extends JComponent {
JCheckBox virtualCheckBox;
boolean checkBoxInit = false;
int preferredWidth = 150;
int preferredHeight = 100;//Mostly ignored as it is
int checkBoxPosX = 5;
int checkBoxPosY = 20;
int checkBoxWidth = preferredWidth;
int checkBoxHeight = 20;
public CheckBoxAccessory()
{
setPreferredSize(new Dimension(preferredWidth, preferredHeight));
virtualCheckBox = new JCheckBox("Virtual stack", checkBoxInit);
virtualCheckBox.setBounds(checkBoxPosX, checkBoxPosY, checkBoxWidth, checkBoxHeight);
this.add(virtualCheckBox);
}
public boolean isBoxSelected()
{
return virtualCheckBox.isSelected();
}
}
The result looks as follows
Disadvantage is that you will not get the whole component to play with but just a relatively small box. Thus the visual look is not what I initially wanted, but when you are no Picasso, you won't care. Advantage of this solution is that you can even react on change of selected file, which is in more details described in https://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html#accessory

Related

How to make an image float above the text in OpenPDF to realize the seal function?

I found that OpenPDF's Image.class seems to have only 6 image positioning methods, and among them, there is only the option to add the image below the text (that is Image.UNDERLYING), but there is no option to let the image float above the text.
The source code of OpenPDF's Image class is as follows:
public static final int DEFAULT = 0;
public static final int RIGHT = 2;
public static final int LEFT = 0;
public static final int MIDDLE = 1;
public static final int TEXTWRAP = 4;
public static final int UNDERLYING = 8;
I want to implement the function of editing the contract. It needs to put a seal image on top of the text, and the position of the image needs to be dynamically set (because the length of the contract text may change). This may involve pagination and absolute positioning. I found that the PdfContentByte class seems to be able to add images to the text, but I don't know how it can dynamically position the images. It would be nice if there was a way to do this in sequence with Document#add like the Paragraph class, but I haven't found it yet.
The effect I want to achieve is roughly like this: Click to view the picture
How can I achieve my needs?
If you want to add something to an existing PDF with OpenPdf, you surely use a PdfStamper.
To add an image above the existing content of some page, simply retrieve the overcontent of the target page from the stamper and add the image to it.

Creating custom swing component out of existing

So, I have this JTexrtArea which is almost perfect for my needs. The only thing wrong with it is the line spacing. I can't set it. (Why not JTextPane? Because spacing CAN be changed in JTextArea and JTextArea is way lighter thatn JTextPane, and I have a bunch of those in my program).
I have asked this question before, and this is the answer that I got from user StanislavL:
To override JTextArea's line spacing take a look at the PlainView (used to render PLainDocument).
There are following lines in the public void paint(Graphics g, Shape a) method
drawLine(line, g, x, y);
y += fontHeight;
So you can adapt the rendering fixing y offset.
In the BasicTextAreaUI method to create view. Replace it with your own implementation of the PlainView
public View create(Element elem) {
Document doc = elem.getDocument();
Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
// build a view that support bidi
return createI18N(elem);
} else {
JTextComponent c = getComponent();
if (c instanceof JTextArea) {
JTextArea area = (JTextArea) c;
View v;
if (area.getLineWrap()) {
v = new WrappedPlainView(elem, area.getWrapStyleWord());
} else {
v = new PlainView(elem);
}
return v;
}
}
return null;
}
I grasp the general idea of what he's telling me to do, but I don't know how to do it.
Also, I wouldn't like to override the default JTextArea "property", I'd like to have a choice - to use the default one or to use a custom one.
Only change in JTextArea code would be from
y += fontHeight,
to
y+= (fontHeight +(or -) additionalSpacing).
How do I achieve this?
Which classes do I use/copy?
Where do I put them?
How do I make them usable?
How do I get the whole thing working?
If you think this is too specific to be useful, maybe someone could write a general tutorial on how to create a custom swing component based 100% on an existing one. Then someone could easely change some values to better adjust it to it's needs.
I am simply going to copy-paste my answer from your other question.
I'd like to change the spacing inbetweem the rows of a JTextArea
My first thought was that overriding javax.swing.JTextArea#getRowHeight would be sufficient. The javadoc clearly states
Defines the meaning of the height of a row. This defaults to the height of the font.
So I was hoping that by overriding this method, you would adjust the definition and you would get more spacing between the rows. Bummer, didn't work. A quick search on the usages of that method in the JDK revealed the same. It is mainly used to calculate some sizes, but certainly not used when painting text inside the component.
By looking at the source code of the javax.swing.text.PlainView#paint method, I saw that the FontMetrics are used, and those you can easily override in the JTextArea. So second approach was to extend the JTextArea (bwah, extending Swing components but it is for a proof-of-concept)
private static class JTextAreaWithExtendedRowHeight extends JTextArea{
private JTextAreaWithExtendedRowHeight( int rows, int columns ) {
super( rows, columns );
}
#Override
public FontMetrics getFontMetrics( Font font ) {
FontMetrics fontMetrics = super.getFontMetrics( font );
return new FontMetricsWrapper( font, fontMetrics );
}
}
The FontMetricsWrapper class basically delegates everything, except the getHeight method. In that method I added 10 to the result of the delegate
#Override
public int getHeight() {
//use +10 to make the difference obvious
return delegate.getHeight() + 10;
}
And this results in more row spacing (and a caret which is way too long, but that can probably be adjusted).
A little screenshot to illustrate this (not as nice as some of the other ones, but it shows that this approach might work):
Small disclaimer: this feels like an ugly hack and might result in unexpected issues. I do hope somebody comes with a better solution.
I personally prefer the solution StanislavL is proposing, but this gives you an alternative
That's a piece of code. It's not finished. Line spacing between wrapped lines is not implemented. You can get full source of WrappedPlainView or PlainView and add your code there to achieve desired line spacing
import javax.swing.*;
import javax.swing.plaf.basic.BasicTextAreaUI;
import javax.swing.text.*;
public class LineSpacingTextArea {
public static void main(String[] args) {
JTextArea ta=new JTextArea();
JFrame fr=new JFrame("Custom line spacing in JTextArea");
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ta.setText("Line 1\nLine 2\nLong text to show how line spacing works");
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setUI(new CustomTextAreaUI());
fr.add(new JScrollPane(ta));
fr.setSize(100,200);
fr.setLocationRelativeTo(null);
fr.setVisible(true);
}
static class CustomTextAreaUI extends BasicTextAreaUI {
public View create(Element elem) {
Document doc = elem.getDocument();
Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
// build a view that support bidi
return super.create(elem);
} else {
JTextComponent c = getComponent();
if (c instanceof JTextArea) {
JTextArea area = (JTextArea) c;
View v;
if (area.getLineWrap()) {
v = new CustomWrappedPlainView(elem, area.getWrapStyleWord());
} else {
v = new PlainView(elem);
}
return v;
}
}
return null;
}
}
static class CustomWrappedPlainView extends WrappedPlainView {
public CustomWrappedPlainView(Element elem, boolean wordWrap) {
super(elem, wordWrap);
}
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
super.layoutMajorAxis(targetSpan, axis, offsets, spans);
int ls=spans[0];
for (int i=0; i<offsets.length; i++) {
offsets[i]+=i*ls;
}
}
}
}

Java - How to get Next Image By Button press

I've managed to add an image into a JPanel in netbeans and display it.I wonder how to get to the next one,by pressing a button.
I've added the image using this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
String Ruta = fileChooser.getSelectedFile().getAbsolutePath();
jTextField1.setText(Ruta);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " +
fileChooser.getSelectedFile().getName());
}
}
And when i press a button called "jButton2" to get the next image,without manually selecting it again from folder.
For example:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
}
Thank You very much.
You have to enumerate images in the directory you are browsing in. When the user selects the file, you should keep a list of all images from that directory in order to retrieve them when user click the next button. As well you can get the file list whenever the user clicks the next button.
maybe something like this:
private File allFiles;
private int currentIndex;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
currentFile = fileChooser.getSelectedFile();
String Ruta = currentFile.getAbsolutePath();
jTextField1.setText(Ruta);
allFiles = currentFile.getParent().listFiles(); // maybe you need a filter to include image files only....
currentIndex = indexOf(allFiles, currentFile);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " + fileChooser.getSelectedFile().getName());
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
if (currentIndex+1 < allFiles.length) {
jtextField1.setText(allFiles[++currentIndex]);
}
}
private int indexOf(File[] files, File f) {
for (int i=0; i+1 < files.length; i++) {
if (files[i].equals(f)) {
return i;
}
}
return -1;
}
Get the parent file if the current image (File.getParent()).
Use one of the File.list..() methods to get the image files.
Sort them into some order that means 'next' to the user.
Iterate that connection until you find the current File then display the next one after that.
I am assuming that you want the next image, if possible in the same directory you chose in your first code excerpt. What you could do is that once the user has chosen the image, you could use Apache's FileUtils to get the extension of files. If the file is a JPG, JPEG, PNG, etc you could load it's location in a List of strings.
This will give you a list of picture paths. You could then use the buttons to traverse the list. Once the button is pressed, you move to the next item, load the image and render it.
EDIT: This is how I would go about it step by step:
Create a global variable of type List.
Create a global variable which will act as a counter;
In your jButton1ActionPerformed method:
Get the parent directory of the file that the user has chosen;
Use Apache's FileUtil class to get the extension of the file names. If the file name is an image, such as PNG, JPG, etc, add it (the path of that file) to your list.
In you jButton2ActionPerformed, increment the counter (if the counter is not smaller than the size of your list, re-initialize it to 0, so as to avoid OutOfBoundsExceptions) and load the the file denoted by the counter using similar logic to your jButton1ActionPerformed method.

How to increase the size of a JFileChooser?

I'm writing a Java app that needs to run on a device with a very high screen resolution. The only UI component that I need to display is a JFileChooser.
Since the screen resolution so high, the FileChooser appears too small. Is there a simple command I can use to make it bigger? Ideally, I'd like to keep the proportions of the components the same, so that the icons grow just as much as the text.
Also, it's important that any changes modify only my application. A global approach to changing the size of the graphics, like using a lower resolution, or changing a system-wide font size, isn't an option for me.
Any ideas?
This class works fine, both resizing JFileChooser window and fonts.
public class JFileChooserArqs {
private Font font = new Font("monospaced",Font.BOLD,16);
private String fileName;
public JFileChooserArqs(String title)
{
fileName = null;
JFileChooser fc = new JFileChooser(".");
fc.setPreferredSize(new Dimension(800,600));
fc.setDialogTitle(title);
setFileChooserFont(fc.getComponents());
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
fileName = fc.getSelectedFile().getAbsolutePath();
}
}
private void setFileChooserFont(Component[] comp)
{
for(int x = 0; x < comp.length; x++)
{
if(comp[x] instanceof Container) setFileChooserFont(((Container)comp[x]).getComponents());
try{comp[x].setFont(font);}
catch(Exception e){}//do nothing
}
}
public String obtemNomeArquivo() {
return fileName;
}
}
I know the answer. Just use chooser.setPreferredSize(new Dimension(int width,int height)); method where chooser is your JFileChooser .
Example:
public class MyFrame extends JFrame(){
JFileChooser chooser = new JFileChooser();
chooser.setPreferredSize(new Dimension(800,600));
//Here show your dialog and do the rest
}
You need to choose suitable layouts to design the user interface. Have a look at CodeRanch thread.
I was going to suggest adding the JFileChooser to a container having a suitable layout, as #AVD suggests. For example, ImageDisplay adds the chooser to BorderLayout.WEST where it's free to grow vertically while adopting the UI delegate's preferred width. Before you abandon that approach, verify that you are not inadvertently defeating that design feature.
If you really need control over the display characteristics of the chooser's subcomponents, you may want to look at these variations of FileBrowser.

InputVerifier and multiple fields

I am working on a form that provides "real-time" validation to the user and I have one problem.
The goal is to put a label near the field (in this case a JSpinner), to show the user if the data is accepted or denied, in the same way that javascript-based validators do.
The problem is that for archieving this, I need to set the value for the corresponding label and the only way I have found to do this is to create as many verifiers as fields, this way:
class MyVerifier extends InputVerifier{
static final double MAX_VALUE = 30;
#Override
public boolean verify(JComponent input) {
JTextField tf = (JTextField) input;
Double value = Double.parseDouble(tf.getText().replace(',', '.'));
return (value>1);
}
#Override
public boolean shouldYieldFocus(JComponent input) {
boolean isValid = super.shouldYieldFocus(input);
if (isValid) {
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("resources/accept.png")));
jLabel1.setText("");
} else {
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("resources/exclamation.png")));
jLabel1.setText("The number of items must be greater than 1");
}
return true;
}
}
Then, the same code for jLabel2... It must be another way to do this.
Thanks in advance.
You could have a Hashmap for the text field and its related label component. Then in the shouldYieldFocus method you retrieve the related label for the text field being validated. You can then set the text/icon of the label appropriately.
You would probably also need a secound Hashmap containg the label and the text message for the error.
You could also use a JDialog as a popup next to the JComponent you are validating. This popup JDialog will have a JLabel that will encapsulate the message you want to display next to the respective Jcomponent. All you have to do is to calculate the position of the popup relative to the Jcomponent you are validating.
You can find a good example here

Categories

Resources