ComboBoxCellEditor - get rid of the text box? - java

I have a TableViewer with a ComboBoxCellEditor. When I click into the cell, first I get a text box (similar to the TextCellEditor) with an arrow next to it. If I click the arrow, I get the drop down list with the values I put into it.
Is there any way for me to skip the text box step? I want it to open up the combo box right away when I click/traverse into the cell. Hand in hand with this is that I also don't want to allow any options other than the ones in the list.
I thought maybe this behavior is controlled by a style, but the only styles I found were
/**
* The list is dropped down when the activation is done through the mouse
*/
public static final int DROP_DOWN_ON_MOUSE_ACTIVATION = 1;
/**
* The list is dropped down when the activation is done through the keyboard
*/
public static final int DROP_DOWN_ON_KEY_ACTIVATION = 1 << 1;
/**
* The list is dropped down when the activation is done without
* ui-interaction
*/
public static final int DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION = 1 << 2;
/**
* The list is dropped down when the activation is done by traversing from
* cell to cell
*/
public static final int DROP_DOWN_ON_TRAVERSE_ACTIVATION = 1 << 3;
and they didn't seem to be relevant. In fact, I set all of them, and I wasn't able to get the functionality I'm looking for.
How can I have the dropbox show without having the accompanying text box?

It's possible to change the styling of the underlying Combo widget by using the constructor:
ComboBoxCellEditor(Composite parent, String[] items, int style)
and passing SWT.READ_ONLY as style

Related

How to get the currently selected cell's indices in JTable immediately after it is highlighted?

I'm building a spread sheet application. But this is not a question like using table.getSelectedColumn() and table.getSelectedRow() to find the selected cell in a JTable.
In Microsoft Excel, when we navigate through cells using arrow keys, the content in the cells are displayed in the Formula Bar immediately after highlighting the cell. Here, the most important thing is, when a cell is highlighted by the selection as above, the value inside the cell is displayed at the sametime. So my question is, how can we do the same in JTable?
I have tried to do something similar using keyEvent listener, but the problem with that is, when a key event is generated, the next cell is being highlighted but the indices of the previous(which was previously highlighted) is being returned in the getSelectedRow() and getSelectedColumn() methods.
Also i tried the ListSelectionListener. but the same fault exists.
If there's any way to get the selected cell's indices immediately after the new cell is highlighted when navigated using arrow keys, that will work. Also an event should be generated since I want to update the formula bar as in Excel. Can someone help me with this?
Thanks in advance!
You can use this simple trick!
Only have to make two excess jTextfields. (can set to be invisible at the run time)
Try to get an idea from below code segment.
private int r;
private int c;
private String buffer;
private void jTextField1KeyTyped(java.awt.event.KeyEvent evt) {
jTextField2.requestFocus();
buffer = jTextField1.getText();
jTable1.getModel().setValueAt(jTextField1.getText(), r, c);
}
private void jTable1KeyTyped(java.awt.event.KeyEvent evt) {
r = jTable1.getSelectedRow();
c = jTable1.getSelectedColumn();
jTable1.putClientProperty("terminateEditOnFocusLost", true);
jTextField1.requestFocus();
}
private void jTextField1FocusGained(java.awt.event.FocusEvent evt) {
buffer = (String)jTable1.getModel().getValueAt(r, c);
jTextField1.setText(buffer);
jLabel1.setText(buffer);
}
private void jTextField2FocusGained(java.awt.event.FocusEvent evt) {
buffer = jTextField1.getText();
jTable1.getModel().setValueAt(buffer, r, c);
jTextField1.requestFocus();
}

Difference between View.INVISIBLE and value of android:invisible

I'm new on Android development, so I'm developing an simple application that hides a textview pressing some button, so in the java code in the method for the OnClick event for the button I set the textview as invisible, I used:
textView.setVisibility(1);
because 1 is the value for "invisible" described in the android reference, but it does not work, so after I used
textView.setVisibility(View.INVISIBLE);
and it works, so When is the "1" value used? and Why is View.INVISIBLE = 4 instead of 1 as the android reference says?
In the android reference I can see that the value Invisible for attribute android:visibility is defined as 1
Both are difference.
According to Android Reference
textView.setVisibility(1);
is same with
textView.setVisibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
If you want to hide the view, use :
textView.setVisibility(View.INVISIBLE);
Or
textView.setVisibility(4);
This is a good question, I checked the Android source code (frameworks/base/core/java/android/view/View.java)
case com.android.internal.R.styleable.View_visibility:
final int visibility = a.getInt(attr, 0);
if (visibility != 0) {
viewFlagValues |= VISIBILITY_FLAGS[visibility]; //here is the key to your question
viewFlagMasks |= VISIBILITY_MASK;
}
break;
Here is the content of VISIBILITY_FLAGS:
private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
The value of the array elements are actually the value shown in Android Reference
/**
* This view is visible.
* Use with {#link #setVisibility} and <a href="#attr_android:visibility">{#code
* android:visibility}.
*/
public static final int VISIBLE = 0x00000000;
/**
* This view is invisible, but it still takes up space for layout purposes.
* Use with {#link #setVisibility} and <a href="#attr_android:visibility">{#code
* android:visibility}.
*/
public static final int INVISIBLE = 0x00000004;
/**
* This view is invisible, and it doesn't take any space for layout
* purposes. Use with {#link #setVisibility} and <a href="#attr_android:visibility">{#code
* android:visibility}.
*/
public static final int GONE = 0x00000008;
So even if you use the android:invisible in the manifest file, Android framework will finally call setVisibility(...) with the value 4.

How do I allow a user to change his font in a JTextPane using a JComboBox?

I'm finding the amount of helpful documentation/tutorials on the internet are lacking when it comes to the topic of JTextPanes. I'm trying to do a simple text processor, and I want it to be able to select a font family from a JComboBox that populates itself based on the fonts a user has installed on their system. However, no matter what I try with experimenting, I can't figure out how to make it work.
What I have is a toolbar class that is built off of a JTextPane. Currently, it has a bunch of style buttons that work to set alignment and bold, italics and underline.
Here's my code:
/**
* The StyleBar is used to customize styles in a Styled Document. It will take a
* JTextPane as an argument for its constructor and then all actions to be taken
* will affect the text in it.
*
* #author Andrew
*/
public class StyleBar extends JToolBar {
private JLabel fontLbl;
private JComboBox fontBox;
// ...Irrelevant stuff to the problem at hand.
/**
* The initEvents method is used to initialize the necessary events for the
* tool bar to actually do its job. It establishes the focus listener to the
* buttons on the bar, and gives each one its individual functionality. It
* also establishes the Font Selection interface.
*/
public void initEvents() {
//For each item in the tool bar, add the focus listener as well as the
//formatting listeners:
boldFormat.addActionListener(new StyledEditorKit.BoldAction()); //boldFormat is
boldFormat.addActionListener(resetFocus); //a JButton
//Ditto for my italicsFormat and underlineFormat button(s) in the toolbar
leftAlign.addActionListener(new StyledEditorKit.AlignmentAction(null,
StyleConstants.ALIGN_LEFT));
leftAlign.addActionListener(resetFocus); //This listener just resets focus
//back onto the TextPane.
//Ditto for my right and centerAlign buttons
//Set up the Font list, and add a listener to the combo box
buildFontMenu();
}
/**
* The buildFontMenu detects all of the SYstem's available fonts and adds
* them to the Font Selection box.
*/
public void buildFontMenu(){
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
final String[] fontNames = ge.getAvailableFontFamilyNames();
for (int i = 0; i < fontNames.length; i++){
//What do I do here to take the entry at String[i] and make it so that when
//the user selects it it sets the font Family in a similar way to that of
//pressing the boldFormat button or the leftAlign button?
}
}
//Everything else is irrelevant
So to sum up my problem: I have no idea how to properly set the listener to the ComboBox such that a) it's sensitive to the individual font selected and b) somehow uses StyledEditorKit.FontFamilyAction to make life easy?
Slash, if I'm approaching anything about this the wrong way, I'd love to hear the right way. As I said, my sources on the internet aren't very clear on the subject.
Thanks so much!
StyledEditorTest puts the Actions in a JToolBar, but the idea is the same. See also Charles Bell's HTMLDocumentEditor, mentioned here. For example,
bar.add(new StyledEditorKit.FontFamilyAction("Serif", Font.SERIF));
bar.add(new StyledEditorKit.FontFamilyAction("SansSerif", Font.SANS_SERIF));
Addendum: As you are using JComboBox, you can forward the event to the corresponding StyledEditorKit Action, which operates on the current selection by default.
JComboBox combo = new JComboBox();
combo.addItem("Serif");
combo.addItem("Sans");
combo.addActionListener(new ActionListener() {
Action serif = new StyledEditorKit.FontFamilyAction("Serif", Font.SERIF);
Action sans = new StyledEditorKit.FontFamilyAction("Sans", Font.SANS_SERIF);
#Override
public void actionPerformed(ActionEvent e) {
if ("Sans".equals(e.getActionCommand())) {
sans.actionPerformed(e);
} else {
serif.actionPerformed(e);
}
}
});
This may be a bit late, but I found myself stuck on the similar problem, and although the previous answer does help, here is a more complete answer for when you want to use all the fonts available on your computer..
Where "fonts" is a string array containing all the desired fonts to be used in your program
final JComboBox jcb = new JComboBox(fonts);
final Action [] actions = new Action[fonts.length];
for (int i = 0; i < actions.length; i++)
{
actions[i] = new StyledEditorKit.FontFamilyAction(fonts[i], fonts[i]);
}
jcb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
for (int i = 0; i < actions.length; i++)
{
if (fonts[i].equals((String)jcb.getSelectedItem()))
{
actions[i].actionPerformed(event);
break;
}
}
}
});

design generic API using abstract method, but have to use final variables when pass to anonymous class. Is there a better way to accomplish this?

I am trying to create an generic API that run on-top of iText. One of the function of this API is to allow the user to split the PDF to invidual page, and allow the user to add list of text onto each pdf page after the split. For example, a pdf of 20 pages, and after run this process, I will have 20 of 1-page-pdf, and the first pdf will have a text 000001 on it, and the last pdf will have 000020 on it pdf. So to accomplish this, I use abstract method that allow the developer to write code on how they want the text to format given the current page number.
public abstract class GenericText {
/**
* The X position of the text. (0, 0) is at the bottom left
*/
private float x;
/**
* The Y position of the text. (0, 0) is at the bottom left
*/
private float y;
/**
* The rotation of the text. Rotation 0, 90, 180, 270
*/
private float rotation;
/**
* <code>com.itextpdf.text.pdf.BaseFont</code>. Determine the font for the text
*/
private BaseFont font;
/**
* Determine the font size of the text
*/
private float fontSize;
/**
* This tells whether text can only be placed first page or on every page
*/
private ComponentPlacement placement;
/**
* Since the text that the user want to insert onto the Pdf might vary
* from page to page, or from logical document to logical document, we allow
* the user to write their own implementation of the text. To give the user enough
* flexibility, we give them the reference to the physical page index, the logical page index.
* #param physcialPage The actual page number that the user current looking at
* #param logicalPage A Pdf might contain multiples sub-documents, <code>logicalPage</code>
* tell the user which logical sub-document the system currently looking at
*/
public abstract String generateText(int physicalPage, int logicalPage);
...
}
PdfPrcessor.java: This is where the split happen
/**
* This is the main process that will split the pdf into individual page, and text to each page
*/
public void splitPdf(String inputPdf, boolean isSplit, List<GenericText> textList,
String outputDir, String baseOutputName, String outputPdfName) throws IOException, DocumentException{
...
PdfReader reader = new PdfReader(inputPdf)
PdfContentByte cb = ... ;
for(int physicalPageIndex=1 ; physicalPageIndex<=reader.getNumberOfPages(); physicalPageIndex ++)
...
//Code to split PDF. Write each page to a separate pdf. For each pdf, insert all text inside `textList` onto the pdf
...
//Insert text
if(textList != null){
for(GenericText textComponent : textList){
String text = textComponent.generateText(physicalPageIndex, logicalPageIndex);
addText(text, cb, textComponent.getFont(), textComponent.getFontSize(), textComponent.getX(), textComponent.getY(), textComponent.getRotation());
}
}
}
...
}
So in my main class I would do this,
final String printName = printNameLookup.get(baseOutputName);
final String seq = config.getPrintJobSeq();
GenericText keyline = new GenericText(90, 640, 0, arial, 7, ComponentPlacement.FIRST_PAGE){
#Override
public String generateText(int physicalPage, int logicalPage) {
return printName + seq + " " + Utils.right(String.valueOf(logicalPage), 6, '0');
}
};
textList.add(keyline);
pdfProcess.splitPdf(inputPdfPath, true, textList, outputDir, baseOutputName, outputPdfName);
This work great, and I think it is very flexible however, printName and seq has be be declared as final in order to pass inside generateText(int physicalPage, int logicalPage). How do I design this so that it wont require final field. Will interface help? I use guava API, and I can do this
ImmutableListMultimap<String, File> groups = Multimaps.index(pdfList,
new Function<File, String>(){
public String apply(File input){
String[] ids = getId(input.getName());
PackageLog pl = logProcessor.lookUp(new Long(ids[0]), ids[1]);
String printName = printNameLookup.get(getPackageName(pl, s));
}
});
logProcessor and printNameLookup is not final, I like the way they design, and I am reading their sources now, but it will take some times, anyone with expert on design knowledge can shed me some light?
Copy them into a final variables and use those instead.
String printName = printNameLookup.get(baseOutputName);
String seq = config.getPrintJobSeq();
// use these in the anonymous class.
final String finalPrintName = printName;
final String finalSeq = seq;
or use arrays
final String[] printName = { printNameLookup.get(baseOutputName) };
final String[] seq = { config.getPrintJobSeq() };
// use printName[0] and seq[0] everywhere.
You have discovered the Template Method design pattern. In this case copying the values into final variables will work.

connecting two JTextAreas in java (updating)

I have a large JTextArea where users can input a bunch of text. My program allows users to select some text and create smaller JTextAreas with the selected text for closer analysis (editing, etc).
The users can update the larger or smaller JTextAreas and when they do, I want the other to update to this new text as well.
My problem is getting the text in the large JTextArea and the smaller ones to reference each other. Is there a good way of doing this? I am having a difficult time splitting up the large text area and using document listeners at the same time. It becomes difficult when there is an overlap of text from the smaller text areas..
ex.
"large text area"
Hello. My name is Matthieu and I am getting frustrated with all these text boxes :p.
"smaller text areas"
Hello.
all these text boxes :p.
text boxes :p.
if I change "text boxes" to "apple" in 2, then box 3 and the full text should update accordingly!
This is probably not what you want to hear, but that sounds like a very bad idea... The first reason is the fact that it is very complicated to manage in the code and design. The second reason is that it makes it more complex for the user to use...
If you really want to implement it this way, I would say the best way would be to keep a list of snippets that are being edited, and add an item to that list that contains the starting index, the original text and which textbox it is being edited in.
Then whenever any changes are made in any textbox, run a method to make the changes to all the textboxes and also updates all the items in the list with updated original text and starting indexes.
I honestly can't see a simple way to do this, and the more textboxes you have, the slower it will get as well.
A much better design in my opinion would be something like a JEditorpane to just display the text (As the big textbox) showing the static text, with a single textbox that displays the selected text and allows editing. This makes the coding pretty trivial, but (Possibly even more importantly), it makes the user interface much simpler and cleaner.
Without knowing exactly why you need this, i can't be sure that the second way would be better, but I would rather use a simpler app as a user.
This could be very difficult, depending on what you want the end result to be. It looks to me like you'd need to track the selection beginning and ending along with each of the boxes. As the text is changed in #2, you could replace the original long text starting at the #2 start index and ending at the end index. That could be ok.
Where I see a problem is if you do something like insert "dumb" in the middle of #2. How would you handle that in #3? Would you shift the start index of #3 to compensate, or would you shift the text that #3 is referencing so it says "dumb test b"?
Before you code this more, I think you should logically work through what you want to happen for, at the least:
inserting characters
deleting characters
changing characters
And probably handle it on a character by character basis with your listeners. It all depends on what you want the end result to be.
All you need to do is subclass the JTextArea and use an interface. The interface can be used to let the sub text areas know that the main text area has been updated.
You will need two subclasses. One will be the main text area, the other will be for the sub panels. Have the sub panels implement an interface so when the parent is updated, they receive the data. Then they can process it how they choose.
The sub text areas are registered with the main text area
Here is a working example:
Main.java
This runs the demo
package Text;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
/**
*
* #author dvargo
*/
public class Main
{
public static void main(String [] args)
{
//build the main text area
JFrame mainFrame = new JFrame();
mainFrame.setSize(700,700);
mainFrame.setTitle("Main Frame");
mainFrame.setLayout(new GridLayout());
//build a sub text area
JFrame subFrameA = new JFrame();
subFrameA.setTitle("Sub Frame A");
subFrameA.setSize(300,300);
subFrameA.setLayout(new GridLayout());
subFrameA.setLocation(mainFrame.getX() + mainFrame.getWidth() + 25, mainFrame.getY());
//build another sub text area
JFrame subFrameB = new JFrame();
subFrameB.setTitle("Sub Frame b");
subFrameB.setSize(300,300);
subFrameB.setLayout(new GridLayout());
subFrameB.setLocation(subFrameA.getX() + subFrameA.getWidth() + 50, subFrameA.getY());
//this is the main text area. Anything typed into here will be sent to the sub text areas
TextField mainTextField = new TextField("Type here and text will appear in the sub frames!!!");
//this sub text area will just mirror the main text area
SubTextField subTextFieldA = new SubTextField();
//this sub text area will add a "-" to the begining of every line
SubTextField subTextFieldB = new SubTextField()
{
#Override
public void update(String text, char lastPressedChar)
{
super.update("- " + text.replace("\n", "\n- "),lastPressedChar);
}
};
//register the sub text areas with the main text areas
mainTextField.register(subTextFieldA);
mainTextField.register(subTextFieldB);
//add them to their frames
mainFrame.add(new JScrollPane(mainTextField));
subFrameA.add(new JScrollPane(subTextFieldA));
subFrameB.add(new JScrollPane(subTextFieldB));
//make everything visible
mainFrame.setVisible(true);
subFrameA.setVisible(true);
subFrameB.setVisible(true);
}
}
I_SubTextField.java
Interface for all sub text areas to implement
package Text;
/**
* Interface to implement to be notified when the text has changed
* #author dvargo
*/
public interface I_SubTextField
{
public void update(String text, char lastChar);
}
TextField.java
Use this as your main text area
package Text;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTextArea;
/**
* Text area
* #author dvargo
*/
public class TextField extends JTextArea
{
//holds all registered sub text areas that are registered for updates
List &lt I_SubTextField &gt registeredSubTextAreas = new ArrayList &lt I_SubTextField &gt ();
/**
* Default constructor
*/
public TextField()
{
this("");
}
/**
* Constructor
* #param text Sets this text area to display this text
*/
public TextField(String text)
{
super(text);
addListener();
}
/**
* Registers a sub text area to get updates when this text area is updated
* #param subTextArea
*/
public void register(I_SubTextField subTextArea)
{
registeredSubTextAreas.add(subTextArea);
}
/**
* Unregisters a sub text area to stop receiving updates
* #param subTextField
*/
public void unRegister(I_SubTextField subTextField)
{
registeredSubTextAreas.remove(subTextField);
}
/**
* Notifies all registered classes when the data in the main window has changed
*/
private void addListener()
{
addKeyListener(new java.awt.event.KeyAdapter()
{
public void keyReleased(java.awt.event.KeyEvent evt)
{
for (I_SubTextField registeredField : registeredSubTextAreas)
{
registeredField.update(TextField.this.getText(), evt.getKeyChar());
}
}
});
}
}
SubTextField.java
Use this for all sub text areas
package Text;
/**
* Represents a sub text area. This can be registered with a TextField to be notified
* when the data has been updated
* #author dvargo
*/
public class SubTextField extends TextField implements I_SubTextField
{
/**
* Default constructor
*/
public SubTextField()
{
super();
}
/**
* Constructor
* #param text Text to display in the text area
*/
public SubTextField(String text)
{
super(text);
}
/**
* Called when the parent TextField is updated. Handle the text as you want
* #param text The text for the main parent
* #param lastPressedChar The last char the user pressed
*/
public void update(String text, char lastPressedChar)
{
setText(text);
}
}
Notice that the SubTextField is a sub class of TextField so you can register additional SubTextFields to a SubTextField.
You can set them up to register with each other and send the unprocessed text to each other. Then each SubTextField can process the text the way it wants. All y ou need to do is override the update()
I would use the same model (Document) in all the text areas. Try to override the View used in JTextArea to show only desired fragment. (See PlainView sources).

Categories