I have a JPanel inside a Anchor Pane inside a JavaFX project. The problem I'm having is the content that's loaded inside the panel is not confined to the panel and cuts off text once it reaches the edge of the panel instead of moving on to the next line.
This is fine however if I test the panel inside a Jframe.
The Anchor panel was created and placed in the user interface using Scene Builder for JavaFX.
Below is the code where I make labels of ranging font sizes(this is to created a Word Cloud) and place them in a JPanel and then return this panel.
public JPanel nnsePairWordCloud() throws SQLException, InstantiationException, IllegalAccessException {
Database databaseConnection = new Database();
databaseConnection.getConnection();
ResultSet nnsePairs = databaseConnection.getNNSEPairInfoFromDatabase();
ResultSet nnseScores = databaseConnection.getNNSESimilarityResultsFromDatabase();
//adding words from the database to the array that will make up the word cloud
while(nnsePairs.next()) {
String wordPair = nnsePairs.getString(1);
WORDS.add(wordPair);
}
//adding each pairs weighting from the database - this will determine the size of the word
while(nnseScores.next()) {
Double wordResult = nnseScores.getDouble(1);
WEIGHTINGS.add(wordResult);
}
System.out.println("cloud data got");
JPanel panel = new JPanel();
panel.setSize(380, 275);
Cloud cloud = new Cloud();
// cloud.setMinWeight(-1);
//cloud.setMaxWeight(1);
cloud.setMaxTagsToDisplay(300);
//Random random = new Random();
for (int i =0; i<WORDS.size(); i++) {
cloud.addTag(new Tag(WORDS.get(i), WEIGHTINGS.get(i)));
}
for (Tag tag : cloud.tags()) {
final JLabel label = new JLabel(tag.getName());
label.setOpaque(false);
label.setFont(label.getFont().deriveFont((float) tag.getWeight() * 10));
panel.add(label);
}
//frame.add(panel);
//frame.setSize(800, 600);
//frame.setVisible(true);
return panel;
}
And here's the code where the panel is returned to and set - creates a SwingNode first and then loads the content. I had to do it this way so I could load the content in the JavaFX UI.
final SwingNode nodeForWordCloud = new SwingNode();
createAndSetSwingContentForWordCloud(nodeForWordCloud);
wordCloudBox.getChildren().add(nodeForWordCloud);
private void createAndSetSwingContentForWordCloud(final SwingNode swingNode) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
swingNode.setContent(new WordCloud().initUI());
} catch (SQLException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(WordNetPairPageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
Figured it out.
If I use a JavaFX FlowPane instead then it solves both the problems I was having. The content now flows within the pane and doesn't cut off and the content loads straight away as its no longer a swing component so it doesn't have to run on a separate thread.
Anyone having similar problems look up how the different layouts in Java FX work as this will help you figure out which one to use. These panels work very differently than they do in Swing.
Related
In my program, I'm using javahelp with helpbroker: all the swing components of the window are automatically generated and positioned.
I would like custom the helpbroker to add a button bar at the bottom of the window like in the image.
What is the easiest way to do it ?
Thanks
The only way to add a help button is to Embed the javahelp in a JFrame:
public class vmHelp {
public static void main(String args[]) {
JHelp helpViewer = null;
String title = "";
try {
// Get the classloader of this class.
ClassLoader cl = vmHelp.class.getClassLoader();
// Use the findHelpSet method of HelpSet to create a URL referencing the helpset file.
// Note that in this example the location of the helpset is implied as being in the same
// directory as the program by specifying "jhelpset.hs" without any directory prefix,
// this should be adjusted to suit the implementation.
String lHelpSetFile = "APP.hs";
URL url = HelpSet.findHelpSet(cl, lHelpSetFile);
if (url == null) {
System.err.println("URL is null, maybe the help set file is wrong: " + lHelpSetFile + ". Look at vmHelp.java");
return;
}
// Create a new JHelp object with a new HelpSet.
HelpSet h = new HelpSet(cl, url);
title = h.getTitle();
helpViewer = new JHelp(h);
// Set the initial entry point in the table of contents.
helpViewer.setCurrentID("top");
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Create a new frame.
JFrame frame = new JFrame();
// Set it's size.
frame.setSize(1000, 800);
// Add the created helpViewer to it.
frame.getContentPane().add(helpViewer);
// Set a default close operation.
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle(title);
// Make the frame visible.
frame.setVisible(true);
}
}
After we can customize the JFrame as we want, it is easy to add a south panel with a close button.
To make all the help buttons listen our javahelp:
pButton.addActionListener(helpAction(pHelpId));
with helpAction that displays our JFrame
Think also to handle keyboard shortcuts, like the helpbroker:
pComponent.registerKeyboardAction(helpAction(pHelpId), KeyStroke.getKeyStroke(KeyEvent.VK_HELP, 0),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
pComponent.registerKeyboardAction(helpAction(pHelpId), KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
To open the help at the wanted section:
helpViewer.setCurrentID("top");
"top" corresponds to tag in the .jhm file
I want to build a bingo got the following source code, which should create a JFrame with 25 buttons placed in a 5x5 matrix. But none of my button gets drawn on the window in any kind.
I ve created a Jpanel on which the buttons are placed, the locations and such are not specific, finetuning will come later, first thing is to even get them drawn on the window.
Bingo Buttons is a class which extends JFrame and simply adds two methods, one to toggle its status from true to false and the other way around and also an method (isSet) to check if the buttons is currently true or false.
bingoField is an String Array which holds nothing but the data which the buttons should get.
I dont get why it does nothing, please help me out. Any kind of help is highly appreciated!
public class BingoFrame extends JFrame {
public static final int BINGOSIZE=25;
public static final int BUTTON_X=50;
public static final int BUTTON_Y=50;
public BingoFrame() {
setResizable(false);
String[] bingoField = null;
BingoButton[] buttons=new BingoButton[25];
try {
bingoField = Utils.getRandomBingoField("Test");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.setTitle("BS Bingo");
this.setResizable(false);
this.setLocation(50, 50);
this.setSize(600, 800);
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(null);
JPanel buttonPanel = new JPanel();
buttonPanel.setBounds(0, 0, 594, 772);
getContentPane().add(buttonPanel);
buttonPanel.setLayout(null);
for(int i=0;i<BINGOSIZE;i++) {
buttons[i] = new BingoButton("Text");
}
//decorate buttons and add an action listener
for(int i=0;i<BINGOSIZE;i++) {
final BingoButton temp = buttons[i];
temp.setText(bingoField[i]);
temp.setBackground(Color.white);
temp.setForeground(Color.blue);
temp.setPreferredSize(new Dimension(BUTTON_X,BUTTON_Y));
temp.addActionListener(new ActionListener() {
boolean toggle = false;
#Override
public void actionPerformed(ActionEvent e) {
if (!temp.isSet()) {
temp.setBackground(Color.blue);
temp.setForeground(Color.white);
} else {
temp.setBackground(Color.white);
temp.setForeground(Color.blue);
}
temp.toggle();
}
});
buttons[i]=temp;
}
//set Location for the buttons
for(int i=0;i<5;i++) {
buttons[i].setLocation(100,(50*i)+10*(i+1));
}
for(int i=5;i<10;i++) {
buttons[i].setLocation(160,(50*i)+10*(i+1));
}
for(int i=10;i<15;i++) {
buttons[i].setLocation(220,(50*i)+10*(i+1));
}
for(int i=15;i<20;i++) {
buttons[i].setLocation(280,(50*i)+10*(i+1));
}
for(int i=20;i<25;i++) {
buttons[i].setLocation(340,(50*i)+10*(i+1));
}
//add buttons to the panel
for(int i=0;i<BINGOSIZE;i++) {
buttonPanel.add(buttons[i]);
}
this.setVisible(true);
I got the answer.
I ve changed the Layout of the Panel to Grid Layout. This alligns the buttons just where they should be in a 5x5 matrix and also with the wanted gap between. This makes also the code for the positioning completly obsolete.
By simply changing the Layout to GridLayout all of my Problems were gone.
I have a main JFrame and three java class that contains different pie charts and these piechart are in panel. I want to call the three pie classes in main jframe. How can l do that?
// I have three of these Chart classes creating different charts inside panels
public class PiePanel extends Observer {
Singleton connCC = Singleton.getInstance();
Connection con = null;
Statement stm = null;
PiePanel(Subject s) {
panel = new JPanel();
sub = s;
}
#Override
public void update() {
try {
con = connCC.getDBconnection();
stm = con.createStatement();
ResultSet rs = stm.executeQuery("Select pet_name as pet, count(pet_ID) AS 'count' from Pet group by pet_name");
DefaultPieDataset dataset = new DefaultPieDataset();
while (rs.next()) {
dataset.setValue(rs.getString("pet"), Integer.parseInt(rs.getString("count")));
}
JFreeChart pieChart = ChartFactory.createPieChart("Header", dataset, true, true, false);
PiePlot plot = (PiePlot) pieChart.getPlot();
plot.setSimpleLabels(true);
PieSectionLabelGenerator gen = new StandardPieSectionLabelGenerator(
"{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0%"));
plot.setLabelGenerator(gen);
panel.add(new ChartPanel(pieChart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(335, 235);
}
});
panel.validate();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
//below is a class that puts all the panels inside a list
public class Subject {
private List<Observer> panel = new ArrayList<Observer>();
public Subject(){
panel.add(new BarPanel(this));
panel.add(new AreaPanel(this));
panel.add(new PiePanel(this));
}
public List<Observer> getChart(){
return panel;
}
}
//main
public class Main {
public static void main(String[] args) {
Subject s = new Subject();
while (true) {
String input = JOptionPane.showInputDialog(null, "Input value:");
if ("d".equals(input) || "w".equals(input)) {
try {
//String value = Integer.parseInt(input);
s.setState(input);
} catch (Exception e) {
System.exit(0);
}
} else {
System.out.println("Wrong Input!");
System.exit(0);
}
}
}
}
Now i want to pass this list in another JFrame class just as in the picture.
Your problem is that you're adding three components in a default fashion to a container that uses BorderLayout, and this results in each added component in the BorderLayout.CENTER covering all the other components added previously. If you want to display three components you can:
Use BorderLayout constants to add the components to different locations within the BorderLayout-using container, or
use a different layout, here perhaps a GridLayout(3, 1), or
if you want a more complex GUI that shows more components, then nest JPanels, each using its own layout manager.
For example, if you want to display the pie charts to the side for instance, then I'd put them into a JPanel that uses a GridLayout, and then add that GridLayout using JPanel to the BorderLayout-using main GUI in the BorderLayout.LINE_END position, or whatever location you desire.
If on the other hand your goal is to swap out one JPanel for another in response to an event, then use a CardLayout to allow easy and efficient swapping of components.
I'm trying to make a combo box in Swing (under Java 7) look like a native combo box. It turns out that a JPopupMenu is used to display the options of the combo box, so it turns into a matter of making a JPopupMenu look native enough.
If I use the default Aqua look and feel, I get square edges, which is not right at all, so we'll throw that idea away right off the bat. So of course, one turns to Quaqua, which is supposed to fix this sort of thing.
public class PopupMenuTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new PopupMenuTest());
}
#Override
public void run() {
try {
UIManager.setLookAndFeel(QuaquaManager.getLookAndFeel());
// Uncomment this for the second example
//PopupFactory.setSharedInstance(new CustomisedScreenPopupFactory());
} catch (Exception ignore) {}
JComboBox<String> comboBox = new JComboBox<>();
comboBox.setModel(new DefaultComboBoxModel<>(
new String[] { "One", "Two", "Three" }));
JFrame frame = new JFrame("Test");
frame.setLayout(new FlowLayout());
frame.add(comboBox);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
This gives me .
Where the code is commented out above, I tried jamming in a custom screen popup factory.
public class CustomisedScreenPopupFactory extends PopupFactory {
private final PopupFactory delegate;
public CustomisedScreenPopupFactory() {
PopupFactory delegate;
try {
Class<? extends PopupFactory> clazz =
Class.forName("com.apple.laf.ScreenPopupFactory")
.asSubclass(PopupFactory.class);
Constructor<? extends PopupFactory> constructor =
clazz.getDeclaredConstructor();
constructor.setAccessible(true); // hacks
delegate = constructor.newInstance();
} catch (Exception ignore) {
delegate = new PopupFactory(); // has to be set to something
}
this.delegate = delegate;
}
#Override
public Popup getPopup(Component owner, Component contents, int x, int y) {
Popup popup = delegate.getPopup(owner, contents, x, y);
try {
Method method = Popup.class.getDeclaredMethod("getComponent");
method.setAccessible(true);
Component component = (Component) method.invoke(popup);
if (component instanceof JWindow) { // always is, so far
JWindow window = (JWindow) component;
JRootPane rootPane = window.getRootPane();
// This call here is what all the rest of the boilerplate was
// added in order to access.
AWTUtilities.setWindowOpaque(window, false);
}
} catch (Exception e) {
Logger.getLogger(getClass()).error("Couldn't customise the popup window", e);
}
return popup;
}
}
This gives me .
Problem is, I want both the rounded corners and the shadow. Is it possible to get both?
Incidentally, I notice that IDEA does get it right, but I couldn't figure out from their source why it would work, so I wonder if it's because it's running on Java 6 and not Java 7...
You can match the system's look and feel like this:
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName);
catch(Exception e){}
that just gets the system L&F, which would be more original than an external L&F anyways.
hope this helps!
I'm trying to implement a feature inside the current program that I'm writing and I wanna learn how to scroll down to specific text inside a JTextArea. For example, lets say I have the following:
JTextArea area = new JTextArea(someReallyLongString);
someReallyLongString would represent a paragraph, or a very large piece of text (in which the vertical scrollbar would be visible). And so what I am trying to do is scroll down to specific text within that text area. For example, lets say someReallyLongString contained the word "the" near the middle of the scrollbar (meaning this word is not visible), how would I scroll down to that specific text?
Thanks, any help would be greatly appreciating.
This is a VERY basic example. This basically walks the document to find the position of the word within the document and ensures that the text is moved to the viewable area.
It also highlights the match
public class MoveToText {
public static void main(String[] args) {
new MoveToText();
}
public MoveToText() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new FindTextPane());
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class FindTextPane extends JPanel {
private JTextField findField;
private JButton findButton;
private JTextArea textArea;
private int pos = 0;
public FindTextPane() {
setLayout(new BorderLayout());
findButton = new JButton("Next");
findField = new JTextField("Java", 10);
textArea = new JTextArea();
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
Reader reader = null;
try {
reader = new FileReader(new File("Java.txt"));
textArea.read(reader, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
JPanel header = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
header.add(findField, gbc);
gbc.gridx++;
header.add(findButton, gbc);
add(header, BorderLayout.NORTH);
add(new JScrollPane(textArea));
findButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Get the text to find...convert it to lower case for eaiser comparision
String find = findField.getText().toLowerCase();
// Focus the text area, otherwise the highlighting won't show up
textArea.requestFocusInWindow();
// Make sure we have a valid search term
if (find != null && find.length() > 0) {
Document document = textArea.getDocument();
int findLength = find.length();
try {
boolean found = false;
// Rest the search position if we're at the end of the document
if (pos + findLength > document.getLength()) {
pos = 0;
}
// While we haven't reached the end...
// "<=" Correction
while (pos + findLength <= document.getLength()) {
// Extract the text from teh docuemnt
String match = document.getText(pos, findLength).toLowerCase();
// Check to see if it matches or request
if (match.equals(find)) {
found = true;
break;
}
pos++;
}
// Did we find something...
if (found) {
// Get the rectangle of the where the text would be visible...
Rectangle viewRect = textArea.modelToView(pos);
// Scroll to make the rectangle visible
textArea.scrollRectToVisible(viewRect);
// Highlight the text
textArea.setCaretPosition(pos + findLength);
textArea.moveCaretPosition(pos);
// Move the search position beyond the current match
pos += findLength;
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
});
}
}
}
This should work:
textArea.setCaretPosition(posOfTextToScroll);
You can get the posOfTextToScroll by the Document model. Read about it, in the Javadoc.
First get the text you set in the text area and build an index using a map to hold the character and the position you find it on.
Based on this the previous answer suggested used the setCaretPosition using the value retrieved from the map.
Add on to the comment by MadProgrammer:
scrollRectToVisible(viewRect) is deprecated as of Java SE9, and it has been replaced by scrollRectToVisible2D(viewRect)
The proper way to get the text to display without using deprecated functions would be:
java.awt.geom.Rectangle2D view = area.modelToView2D(pos); // View where pos is visible
area.scrollRectToVisible(view.getBounds()); // Scroll to the rectangle provided by view
area.setCaretPosition(pos); // Sets carat position to pos