How to make text pane accept pastes but block typing - java

My Goal is :
having a text pane where user can paste text only(with OS not a button!!!) and can't type in to the pane
because: can't have submit button (this is a must requirement - I know that it's not logical)
after pasting: the text-pane becomes not editable for user, and the program will change background at specific chars.
after button "clear filed" pressed - the program clears the pane and returns to initial state
My Problem: How to make text pane accept pastes but block typing
so far I made only JPanel with the text pane itself and all the controls will be in different JPanel
public class textPanel extends JPanel{
private JTextPane text;
public textPanel ()
{
setLayout(new BorderLayout());
text = new JTextPane(); //12,81
text.setBorder(BorderFactory.createLoweredBevelBorder());
add(text,BorderLayout.CENTER);
StyledDocument doc = text.getStyledDocument();
setBackground(Color.LIGHT_GRAY);
setPreferredSize(new Dimension(1000, 210));
}
thanks for help

Override public void paste() method of your. By default your JTextPane is not editable (setEditable(false)).
The paste() method's source in JTextComponent is
public void paste() {
if (isEditable() && isEnabled()) {
invokeAction("paste", TransferHandler.getPasteAction());
}
}
So you just make it editable, call super.paste(), and set the editable=false back after the super call.

Related

How to edit a JComboBox with text selected in JEditorPane

I have a UI with two components - a JEditorPane and a JComboBox. My goal is to be able to type something into the JEditorPane, select a portion of the text, and while it is still selected type and/or select a value in an editable JComboBox.
This is for a text editor type of program where I want to change the font size of just the selected text in the editor pane. Where the font size is coming from the editable combo box. To clarify, I'm not asking how to apply styles to the text, I'm asking how to select a value in the combo box without losing the focus/selection in the JEditorPane.
Here's the code for the UI, but I wasn't sure where to begin doing anything with the focus...
public static void main(String [] args)
{
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
JComboBox<String> combo = new JComboBox(new String [] {"Hello", "World"});
contentPane.add(combo);
JEditorPane editor = new JEditorPane();
contentPane.add(editor);
frame.setContentPane(contentPane);
frame.pack();
frame.setVisible(true);
}
I'm asking how to select a value in the combo box without losing the focus/selection in the JEditorPane.
You don't lose the selection of the text in the editor pane when you select an item from the combo box. The selection remains, but it is just not painted until the editor pane regains focus.
So the easiest way to do this is to use a JMenuItem. Read the section from the Swing tutorial on Text Component Features for an example that does this.
If you still want to use the combo box then you can add Integer values to the combo box then the code in your ActionListener for the combo box would look something like:
#Override
public void actionPerformed(ActionEvent e)
{
Integer value = (Integer)comboBox.getSelectedItem();
Action action = new StyledEditorKit.FontSizeAction("Font size", value);
action.actionPerformed(null);
}
The StyledEditorKit actions extend from TextAction. The TextAction knows the last text component that had focus and therefore the font change is applied to that text component.
If you really want the text field to show the selection then you need to create a custom Caret and override the focusLost method to NOT invoke setSelectionVisible(false) (which is the default behaviour.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class DefaultCaretTest extends JFrame
{
public DefaultCaretTest()
{
JTextField textField1 = new JTextField("Text Field1 ");
JTextField textField2 = new JTextField("Text Field2 ");
textField1.setCaret(new SelectionCaret());
textField2.setCaret(new SelectionCaret());
textField1.select(5, 11);
textField2.select(5, 11);
((DefaultCaret)textField2.getCaret()).setSelectionVisible(true);
add(textField1, BorderLayout.WEST);
add(textField2, BorderLayout.EAST);
}
static class SelectionCaret extends DefaultCaret
{
public SelectionCaret()
{
setBlinkRate( UIManager.getInt("TextField.caretBlinkRate") );
}
public void focusGained(FocusEvent e)
{
setVisible(true);
setSelectionVisible(true);
}
public void focusLost(FocusEvent e)
{
setVisible(false);
}
}
public static void main(String[] args)
{
DefaultCaretTest frame = new DefaultCaretTest();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
Of course the selection will remain when focus is on any other component, not just the combo box.
You can also use:
comboBox.setFocusable(false);
Since the combo box can't gain focus the focus will remain on the text component, but the problem with this is that the user won't be able to use the keyboard to select a font size from the combo box. A proper GUI design always allows the user to use either the keyboard or the mouse to perform an action.

Repaint TextFile in JPanel

I quite new in java and I encounter a problem with repaint a TextFile in my JPanel, this is code:
JPanel paneldol = new JPanel();
paneldol.add(new JButton(new AbstractAction("Oblicz pole i obwód")
{
#Override
public void actionPerformed(ActionEvent e) {
paneldol.repaint();
paneldol.revalidate();
}
}
));
paneldol.add(new TextField(model.getPole(), 10));
paneldol.add(new TextField(model.getObwod(), 10));
this.add(paneldol, BorderLayout.PAGE_END);
As you see TextField have metod that generate string, so when i click in button I want to repain panel to have new value in my Textfield, Is this possibly?
so when i click in button I want to repain panel to have new value in my Textfield, Is this possibly?"`
If all you want to do is to change the text in text field on button push, then you should give your class a JTextField variable (or multiple JTextField variables), assign a JTextField object to the variable, and this to the GUI. Then when within your button's listener, simply set the text of the JTextField via its setText(...) method. There's no need to call repaint() or revalidate() as they will do nothing useful in this situation.
Also don't mix AWT with Swing components. Use JTextFields not TextFields.

How to disable text selection on JTextArea Swing

I don't want the user to select the content on JTextArea. I use setEditable(false) but it's not working. How to disable this feature of JTextArea component. Could you give me advise. Thanks.
If you would like to just disable text selection on any swing control such as JtextArea you can use the coding below:
JtextArea.setHighlighter(null);
This one line of coding will help disable the text selection and can be placed in the constructor or within a initialized method upon Frame execution.
Hope this helps
You can set the "mark" equal to the "dot" of the caret. When these values are equal there is no text selection:
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class NoTextSelectionCaret extends DefaultCaret
{
public NoTextSelectionCaret(JTextComponent textComponent)
{
setBlinkRate( textComponent.getCaret().getBlinkRate() );
textComponent.setHighlighter( null );
}
#Override
public int getMark()
{
return getDot();
}
private static void createAndShowUI()
{
JTextField textField1 = new JTextField("No Text Selection Allowed");
textField1.setCaret( new NoTextSelectionCaret( textField1 ) );
textField1.setEditable(false);
JTextField textField2 = new JTextField("Text Selection Allowed");
JFrame frame = new JFrame("No Text Selection Caret");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(textField1, BorderLayout.NORTH);
frame.add(textField2, BorderLayout.SOUTH);
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Late to the party, but here are my findings. I had tried using setEnabled(false) on a JTextPane displaying static (not user-modifiable) content such as line numbers (for another text component). This one alone prevents the component from getting focus and text selection on it:
JTextArea textArea = new JTextArea("Static text");
textArea.setEnabled(false);
My problem with setEnabled(false) is that it forces a single disabledTextColor for all of the text (I've traced it down to javax.swing.text.GlyphView.paint()), while I want to style individual lines/chunks. I've finally tried setFocusable(false) that appears to satisfy both needs:
Not user focusable and no user selection on it;
Custom text color could be applied to individual parts of the content, or it just doesn't change the text color to the disabled one.
The complete solution needs additional setEditable(false) to prevent the mouse cursor from changing but that's it – two properties:
JTextArea textArea = new JTextArea("Static text");
textArea.setEditable(false);
textArea.setFocusable(false);

JScrollPanes, JTextAreas, and maximum sizes

Context: In a flashcard application, I have a view for a CardData (a data structure representing one side of a flashcard). It has, in its most basic form, a String text. The view (known as CardDataView) consists of the text in an uneditable JTextArea inside a JScrollPane.
At one point, I need to line up (vertically) a bunch of these CardDataViews, so I put them in a vertical Box.
Here's the problem: when I expand the window from it's "preferred" size (as determined by pack) and then size it back down, the JScrollPane adds a horizontal scroll bar and allows me to scroll horizontally in the text field. Essentially, it's sizing up the text area when it shouldn't be.
Here's my code (stripped down and simplified):
public class DebugTest {
public static void main(String[] args) {
CardDataView cdv = new CardDataView(new CardData(
"Lorem ipsum dolor sit amet filler filler filler"));
JFrame frame = new JFrame();
frame.add(new JScrollPane(cdv), BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class CardData {
private String text; // text on the card
/*
* NOTE: This class has been simplified for SSCCE purposes. It's not really
* just a String field in production; rather, it has an image and other
* properties.
*/
public CardData(String text) {
super();
this.text = text;
}
public String getText() {
return text;
}
}
class CardDataView extends Box {
private JTextArea txtrText; // the text area for the text
/*
* NOTE: As with CardData, this class has been simplified. It's not just a
* JTextArea; it's also an ImageView (custom class; works fine), among other
* things.
*/
public CardDataView(CardData data) {
super(BoxLayout.Y_AXIS);
txtrText = new JTextArea();
txtrText.setLineWrap(true);
txtrText.setRows(3);
txtrText.setEditable(false);
txtrText.setWrapStyleWord(true);
final JScrollPane scrollPane = new JScrollPane(txtrText);
add(scrollPane);
txtrText.setText(data.getText());
}
}
Now, something that really confuses me (unless I'm going about it wrong) is that if I essentially inline the data and view classes, by just creating a text area with text and a scroll pane (even with setting the same number of rows, same wrap settings, etc.), it behaves as expected. What could be happening?
Concerns:
- All imports are in order.
- If you're wondering why CardLayoutView is a Box: in production, it has more than just a text box. The same error happens when it's a JPanel and I setLayout instead of super.
- The same glitch happens if I don't use the CardData class at all (and set the text area's text manually).
Any ideas?
Putting my comment to answer :
Use GridBagLayout with GridBagConstraints.VERTICAL/NONE as the gridBagLayoutObject.fill value, instead of BoxLayout. Since when adding components to the CENTER of the JFrame, BorderLayout never respects the preferredSize() for the CENTER component. Hence try to add your stuff to a JPanel and then put this JPanel at the CENTER of the JFrame.

Java GUI - JPanels, JFrames, JButtons

I'm trying to open a window that has both an image and buttons in it. But I can't seem to figure out how to add the button. The image displays great and the menu works fine, but no matter where I add the button (into the JLabel, JPanel, or JFrame), it doesn't ever show...
Main:
public static void main(String[] args) {
GUI myGUI = new GUI();
myGUI.show();
}
GUI class: openImage is called when using the menu. The image then displays, but no button.
private JFrame myFrame;
private JPanel myPanel;
private JLabel myLabel;
public GUI()
{
myFrame = new JFrame();
initializePanel();
}
public void show()
{
myFrame.setSize(600,600);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.addMouseListener(this);
setupMenu(myFrame);
myFrame.setVisible(true);
}
private void initializePanel()
{
myPanel = new JPanel();
myPanel.setPreferredSize(new Dimension(500,500));
//myPanel.setLayout(new BorderLayout());
}
private void openImage(String fileName)
{
try {
myImage = ImageIO.read(new File(fileName));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myLabel = getJLabel();
JButton button = new JButton("ButtonClick");
button.addActionListener(this);
myFrame.setContentPane(myLabel);
myPanel.add(button);
myFrame.getContentPane().add(myPanel);
myFrame.pack();
myFrame.setSize(600,600);
}
private void setupMenu(JFrame window) {
JMenuBar menubar = new JMenuBar();
JMenu file = new JMenu("File");
JMenuItem open = new JMenuItem("Open");
open.addActionListener(this);
file.add(open);
menubar.add(file);
window.setJMenuBar(menubar);
}
Your main issue is your setting the contentPane to be a JLabel -- don't do this! The contentPane needs to be opaque, needs to be built to be easily used as a Container and in your case, really should be a JPanel. JLabel I believe uses a null layout so it's no surprise that your code shows no button. If you want to show a background image, make have myPanel constructed from an anonymous class that extends JPanel, override the paintComponent method in this class (calling super.paintComonent first in the method), and draw the image in this method. Then you can add components to the contentPane which will now use a FlowLayout (the default for a JPanel) and it will be opaque by default.
Also, if your goal is to swap items displayed in your GUI, use a CardLayout to do the swapping for you as this layout makes swapping components a breeze.
really don't know, depends of method(s) how you are added picture to the JLabel, JPanel, or JFrame, but maybe for simle Container that contains a few, only one-two JComponents is there crazy idea, without side effects, with idea to display picture and to add there JButton:
JLabel is very similair JComponent to the JPanel, and is by default translucent and very simple implements Icon/ImageIcon, then you'll only to call myLabel.setIcon(myPicture)
to the all of JComponents you are/could be able to add another JComponent by using some of LayoutManager (Box, Flow, GridBagLayout)
You tried to set the label as the content pane and then tried to add the panel to that image which doesn't make sanse at all.
Change it so you add the label to the panel and have the panel as content pane:
Like this:
You have this line which is the problem. It doesn't make much sense:
myFrame.setContentPane(myLabel);
Try instead:
myFrame.getContentPane().add(myLabel);

Categories