What I need is for a user to be able to click any tag on a web page. Once they click the tag a new button appears in a GridPane. When I click the new button in the GridPane a small dialog box appears with all the attributes that exist in the tag.
Step by step:
I load google.com
I click the link at the foot "About"
A button appears in the GridPane
I click the button that just appeared
A smaller window appears that lists:
About
xpath: id("fsl")/A[3] //this is a the xpath of the click which I use js
class: _Gs
href: //www.google.com/intl/en/about.html?fg=1
Then I close this smaller window and click Business
A new button appears in the gridpane
I click the button that just appeared
A smaller window appears with new list of attributes:
Business
xpath: id("fsl")/A[2]
class: _Gs
href: //www.google.com/services/?fg=1
That's the idea.
The issue is when I click Business, the xpath of About is replaced with the xpath for Business. When I open the content of About in the gridpane everything is still the same except xpath is now id("fsl")/A[2] instead of id("fsl")/A[3]
It all starts in the worker
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>(){
public void changed(ObservableValue ov, State oldState, State newState){
if(newState == javafx.concurrent.Worker.State.SUCCEEDED){
//attach listener to all tags "*"
EventListener listener = new EventListener(){
public void handleEvent(org.w3c.dom.events.Event evt) {
addNewInstruction(evt);
setXPath();
}
};
setListenerByTagNames(listener, "a");
}
}
});
//xpath method
private void setXPath(){
JSObject hrefWindow = (JSObject) engine.executeScript("window");
hrefWindow.setMember("java", bridge);
engine.executeScript("var links = document.getElementsByTagName(\"*\");"+
"for (var i = 0; i < links.length; i++) {"+
"links[i].addEventListener(\"click\", function(){"+
"document.onclick = function(event) {" +
"if (event===undefined) event= window.event;" +
"var target= 'target' in event? event.target : event.srcElement; " +
"var root= document.compatMode==='CSS1Compat'? document.documentElement : document.body;" +
"var mxy= [event.clientX+root.scrollLeft, event.clientY+root.scrollTop];" +
"var path= getPathTo(target);" +
"var txy= getPageXY(target);" +
"java.log(path);" +
"}" +
"});"+
"}"+
"function getPathTo(element) {" +
"if (element.id!=='')" +
"return 'id(\"'+element.id+'\")';" +
"if (element===document.body)" +
"return element.tagName;" +
"var ix= 0;" +
"var siblings= element.parentNode.childNodes;" +
"for (var i= 0; i<siblings.length; i++) {" +
"var sibling= siblings[i];" +
"if (sibling===element)" +
"return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';" +
"if (sibling.nodeType===1 && sibling.tagName===element.tagName)" +
"ix++;" +
"}" +
"}" +
"function getPageXY(element) {" +
"var x= 0, y= 0;" +
"while (element) {" +
"x+= element.offsetLeft;" +
"y+= element.offsetTop;" +
"element= element.offsetParent;" +
"}" +
"return [x, y];" +
"}");
}
The javabridge class
public class JavaBridge extends Amz
{
public String text = "EMPTY STRING";
public void log(String text){
this.text = text;
}
}
The instruction method
private void addNewInstruction(org.w3c.dom.events.Event evt){
String htmlTagName = ((Element)evt.getTarget()).getTagName();
if(instructionIncrementCol == 10){
instructionIncrementRow++;
instructionIncrementCol= 0;
}
final Button button = new Button(htmlTagName);
button.setOnAction(
new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
//Grid Specs
GridPane primaryGrid = new GridPane();
Element element = ((Element)evt.getTarget());
primaryGrid.setVgap(4);
primaryGrid.setPadding(new Insets(5, 5, 5, 5));
TitledPane titleSlider = new TitledPane();
titleSlider.setText("Instructions");
titleSlider.setContent(primaryGrid);
titleSlider.setContent(primaryGrid);
final GridPane secondGrid = new GridPane();
secondGrid.setVgap(4);
secondGrid.setPadding(new Insets(20));
secondGrid.setPrefHeight(100);
ScrollPane sp = new ScrollPane(secondGrid);
sp.setHbarPolicy(ScrollBarPolicy.ALWAYS);
sp.setMaxHeight(400);
primaryGrid.add(sp, 0, 1);
GridPane.setHgrow(sp, Priority.ALWAYS);
GridPane.setVgrow(sp, Priority.ALWAYS);
//Form
int rowOnePos = 0;
int rowTwoPos = 1;
int rowThreePos = 2;
int loopRowPos = 3;
String tagType = element.getTagName();
if(tagType.equals("INPUT")){
createInputInstructionObject(secondGrid,rowOnePos, element);
}else{
Button click = new Button("Click");
secondGrid.add(click, 0, rowOnePos);
click.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent e){
sql.insertRow("click", element.getAttribute("href"));
//writeToFile("click,"+((Element)evt.getTarget()).getAttribute("href"));
}
});
Text textLabel = new Text("Text");
TextField textContentValue = new TextField(element.getTextContent());
Button grabDataText = new Button("Grab");
textContentValue.setPrefWidth(300);
secondGrid.add(textLabel, 0, rowTwoPos);
secondGrid.add(textContentValue, 1, rowTwoPos);
secondGrid.add(grabDataText, 2, rowTwoPos);
textContentValue.setPrefWidth(300);
}
//xpath
Text xpathLabel = new Text("XPath");
final String stay = bridge.text+" ";
TextField xpathValue = new TextField(stay);
Button grabDataxpath = new Button("Grab");
secondGrid.add(xpathLabel, 0, rowThreePos);
secondGrid.add(xpathValue, 1, rowThreePos);
secondGrid.add(grabDataxpath, 2, rowThreePos);
//all attributes for this tag
NamedNodeMap attributes = element.getAttributes();
for(int i = 0; i < attributes.getLength(); i++){
//create row for each attribute
createInstructionObject(attributes, i, secondGrid, loopRowPos);
}
final Stage dialog = new Stage();
Scene dialogScene = new Scene(primaryGrid, 500, 500);
dialog.setScene(dialogScene);
dialog.show();
}
});
instructionSecondaryGrid.add(button,instructionIncrementCol,instructionIncrementRow);
instructionIncrementCol++;
}
Your code isn't very understandable - lots of references are declared and not used, or not declared and then referred to (the latter means it won't compile) - but as far as I can understand it you just need to create the dialog once for each button, instead of recreating it every time the button is pressed:
private void addNewPane(org.w3c.dom.events.Event evt){
final Button button = new Button(htmlTagName);
final Stage dialog = new Stage();
GridPane primaryGrid = new GridPane();
Element element = ((Element)evt.getTarget());
primaryGrid.setVgap(4);
primaryGrid.setPadding(new Insets(5, 5, 5, 5));
TitledPane gridTitlePane = new TitledPane();
GridPane secondGrid = new GridPane();
secondGrid.setVgap(4);
secondGrid.setPadding(new Insets(20));
secondGrid.setPrefHeight(100);
ScrollPane sp = new ScrollPane(secondGrid);
sp.setHbarPolicy(ScrollBarPolicy.ALWAYS);
sp.setMaxHeight(400);
int rowThreePos = 2;
//text content of data
secondGrid.add(new Text("XPath"), 0, rowThreePos);
secondGrid.add(new TextField(holdXPath), 1, rowThreePos);
secondGrid.add(new Button("Grab"), 2, rowThreePos);
primaryGrid.add(sp, 0, 1);
GridPane.setHgrow(sp, Priority.ALWAYS);
GridPane.setVgrow(sp, Priority.ALWAYS);
gridTitlePane.setText("Forms");
gridTitlePane.setContent(primaryGrid);
gridTitlePane.setContent(primaryGrid);
Scene dialogScene = new Scene(primaryGrid, 500, 500);
dialog.setScene(dialogScene);
button.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
dialog.show();
}
});
SecondaryGrid.add(button,IncrementCol,IncrementRow);
IncrementCol++;
}
Finally found a solution. I ended up using javascript to insert the XPath into SQLite DB, upon loading page, and assigning a new attribute to the tag with the ID of the XPath in the DB.
like so:
Click Me
//the JS
var anchors = document.getElementsByTagName("a");
for (var i = 0; i < anchors.length; i++) {
java.insertIntoDB(getXPathID(anchors[i]));
anchors[i].setAttribute("mycustomAttr", java.getMaxId());
}
Related
I am trying to basically 1) create random DFAs and 2) show them one after another using JFrame. I have worked out how to create DFAs randomly, let GraphViz take care of visualizing them and save them in a .png file, and then display them in a JFrame. The DFAs are created within a loop, in which a function displayAutomaton is called, which takes care both of creating the .png, and of displaying it.
for(int i = 2; i < 10; i++) {
AutomatonConverter.displayAutomaton(createRandomDFA(i));
while(AutomatonConverter.jFrameExists) System.out.println("this works");
}
The code of displayAutomaton is the following:
public static void displayAutomaton(Automaton A) {
// Create the automaton-dependent file name
String fileName = getAutomatonName(A);
// Convert the Automaton and save it in a .png
convertAutomaton(A, fileName);
JFrame frame = new JFrame();
// This static variable is used to determine whether the window
// has been closed, so that the next iteration in the loop can start
jFrameExists = true;
ImageIcon icon = new ImageIcon(fileName);
JLabel label = new JLabel(icon);
frame.add(label);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
jFrameExists = false;
frame.dispose();
}
});
frame.pack();
frame.setVisible(true);
}
As you can see, I use a static variable jFrameExists in my main loop to infer if the window has been closed, because I would like to open the different images of the automatons consecutively. To this end, I've overridden the frame's Window-Listener. Here's the weird part: as you can see above, after displaying the automaton, a while-loop asks if jFrameExists has been set to false (which happens, again, when the window is closed). And currently, all this works. Each created automaton is shown in a differet JFrame, one after another, and each new window only opens after I close the previous one, which is exactly what I want - but I obviously don't want to print "this works" every time, so I tried to remove this simple instruction. However, then the code does not work anymore - this way, only the first image is shown, and after I close it, nothing happens.
I have tried simply ending the line there, asserting true (while(AutomatonConverter.jFrameExists) assert true;), and creating empty void methods to put here (while(AutomatonConverter.jFrameExists) doNothing();), but nothing works correctly - again, this way only the first image is shown, and the loop does not seem to continue to the next automaton. I just can't figure out why. Anybody have any idea?
Edit: Here's a generalized version of my code that is hopefully more understandable (ignore the code in convertAutomaton and createRandomDFA, I just added that for completeness' sake):
public class main {
static boolean jFrameExists = false;
public static void convertAutomaton(Automaton A, String fileName) {
// Creates a png of the automaton A and saves it under the fileName
GraphViz gv = new GraphViz();
gv.addln(gv.start_graph());
gv.addln("rankdir=LR;");
String startName;
String shape;
if(A instanceof DFA) {
// Create the starting node
State q0 = ((DFA) A).getQ0();
startName = "\"" + q0.getName() + "start\"";
shape = A.getF().contains(q0) ? "doublecircle" : "circle";
// Add the node itself...
gv.addln("node [shape = " + shape + "]; \"" + q0.getName() +"\";");
// ... and its corresponding entry arrow
gv.addln("node [shape = point]; " + startName + ";");
gv.addln(startName + " -> \"" + q0.getName() + "\"");
// Create all accepting nodes
for(State s : A.getF()) {
if(!((DFA) A).getQ0().equals(s)) gv.addln("node [shape = doublecircle]; \"" + s.getName() +"\";");
}
} else {
// Create all starting nodes
for(State s : ((NFA) A).getQ0()) {
startName = "\"" + s.getName() + "start\"";
shape = A.getF().contains(s) ? "doublecircle" : "circle";
// Add the node itself...
gv.addln("node [shape = " + shape + "]; \"" + s.getName() +"\";");
// ... and its corresponding entry arrow
gv.addln("node [shape = point]; " + startName + ";");
gv.addln(startName + " -> \"" + s.getName() + "\"");
}
// Create all accepting nodes
for(State s : A.getF()) {
if(!((NFA) A).getQ0().contains(s)) gv.addln("node [shape = doublecircle]; \"" + s.getName() +"\";");
}
}
gv.addln("node [shape = circle];");
// Create all transitions
ArrayList<State> reachable;
String sName, s2Name;
for(State s : A.getStates()) {
for(char c : Automaton.alphabet) {
sName = "\"" + s.getName() + "\"";
reachable = s.delta(c);
for(State s2 : reachable) {
s2Name = "\"" + s2.getName() + "\"";
gv.addln(sName + " -> " + s2Name + " [ label = \"" + c + "\" ];");
}
}
}
gv.add(gv.end_graph());
File out = new File(fileName);
gv.writeGraphToFile(gv.getGraph(gv.getDotSource(), type), out );
}
}
public static void displayAutomaton(Automaton A) {
String fileName = "automaton.png"
convertAutomaton(A, fileName);
JFrame frame = new JFrame();
jFrameExists = true;
ImageIcon icon = new ImageIcon(fileName);
JLabel label = new JLabel(icon);
frame.add(label);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
jFrameExists = false;
frame.dispose();
}
});
frame.pack();
frame.setVisible(true);
}
public static Automaton createRandomDFA(int numberOfStates) {
// Create the states
ArrayList<State> states = new ArrayList<State>();
for(int i = 0; i < length; i++) states.add(new State(Integer.toString(i)));
// Create random transitions
Random r = new Random();
State rState;
for(State s : states) for(char c : Automaton.alphabet) {
rState = states.get(r.nextInt(length));
s.addTransition(c, rState);
}
// Create random accepting states
ArrayList<State> F = new ArrayList<State>();
for(State s : states) {
if(r.nextInt(length) == length - 1) F.add(s);
}
if(F.size() == 0) F.add(states.get(r.nextInt(length)));
// Create random starting state
State q0 = states.get(r.nextInt(length));
return new DFA(states, q0, F);
}
}
public static void main(String[] args) {
for(int i = 2; i < 10; i++) {
displayAutomaton(createRandomDFA(i));
while(jFrameExists) System.out.println("waiting until the window is closed");
}
}
}
That's basically it. I know it's weird to not implement all the visualization stuff in its own class and to simply close the window instead of adding a button handling the functionality I want, but I essentially don't want to visualize anything in the long run, this was just supposed to test if the Automatons are created correctly. I will try different approaches that are more coherent with coding standards in the future, but I would nonetheless really like to know why calling System.out.println() makes a difference.
public void employeeMenu()
{
//ADD LOG OUT BUTTON SOMEWHERE
//setting stage
StackPane empMenuStage = new StackPane();
VBox empBox = new VBox(new Label("Employee Menu"));
empMenuStage.getChildren().add(empBox);
Scene empScene = new Scene(empMenuStage, 500, 500);
Stage empStage = new Stage();
empStage.setScene(empScene);
empStage.setTitle("Employee Menu");
TabPane tabPane = new TabPane();
Tab bookingReport = new Tab("Booking Report");
Tab checkOutGuest = new Tab("Check Out Guest");
Tab createGuestAccount = new Tab("Create Guest Account");
Tab editGuestInformation = new Tab("Edit Guest Info");
Tab createNewEmpAccount = new Tab("Create new Employee Account");
Tab editEmployeeAccount = new Tab("Edit Employee Account");
Tab editRoomStatus = new Tab("Edit Room Status");
tabPane.getTabs().add(bookingReport); //mitchell
tabPane.getTabs().add(checkOutGuest); //emma
tabPane.getTabs().add(createGuestAccount); //joey
tabPane.getTabs().add(editGuestInformation);
tabPane.getTabs().add(createNewEmpAccount);
tabPane.getTabs().add(editEmployeeAccount);
tabPane.getTabs().add(editRoomStatus);
VBox tabBox = new VBox(tabPane);
Scene scene = new Scene(tabBox, 500, 500);
empStage.setScene(scene);
empStage.setTitle("Employee Menu");
empStage.close();
empStage.show();
}
public Tab displayEmpMenu(Stage empStage)
{
//button for check out a value guest
//then enter name of value guest
//Enter room of value guest
//Confirmation Message (pick Y or N)
Tab test = new Tab("hi");
Button valueGuest = new Button("Check out Value Guest");
Button generalGuest = new Button("Check out General Guest");
valueGuest.setOnAction(e -> checkOutVG());
generalGuest.setOnAction(e -> checkOutGeneral());
GridPane layout = new GridPane();
layout.setPadding(new Insets(10, 10, 10, 10 ));
layout.setVgap(8);
GridPane.setConstraints(valueGuest, 0, 0);
GridPane.setConstraints(generalGuest,0, 1 );
layout.getChildren().addAll(valueGuest, generalGuest);
Scene scene = new Scene(layout, 650, 200 );
empStage.setScene(scene);
empStage.setTitle("Check Out Guest");
empStage.show();
//button for check out a general guest
//button for return to employee menu
return test;
}
public void checkOutVG()
{
TextField vgName = new TextField("Enter name of value guest");
String vgN = vgName.getText();
Label name = new Label("Value Guest Name");
TextField vgRoom = new TextField("Enter room of value guest");
Label roomNum = new Label("Value Guest Room");
double room = Double.parseDouble(vgRoom.getText());
int room1 = (int)room;
freeThisRoom(room1);
Label vgRoom1 = new Label("Value Guest Room");
TextField vgconfirm = new TextField("Confirmation: "
+ vgN + " is checking out of "
+ room1 + "(Y/N)");
vgconfirm.getText();
String text = "";
if (vgconfirm.getText().equalsIgnoreCase("Y"))
{
text = "Done. " + vgN + "is checked out of "
+ room1;
}
else
{
text = "You entered no. Please re-enter information.";
}
}
public void checkOutGeneral()
{
TextField name = new TextField("Enter name of general guest");
Label ggname = new Label("General Guest Name");
String name1 = name.getText();
TextField room = new TextField("Enter room number of general guest");
Label roomNum = new Label("General Guest Room");
double ggNum = Double.parseDouble(room.getText());
int ggRoom = (int)ggNum;
freeThisRoom(ggRoom);
TextField vgconfirm = new TextField("Confirmation: "
+ name + " is checking out of "
+ ggRoom + "(Y/N)");
vgconfirm.getText();
String text = "";
if (vgconfirm.getText().equalsIgnoreCase("Y"))
{
text = "Done. " + name + "is checked out of "
+ ggRoom;
}
else
{
text = "You entered no. Please re-enter information.";
}
}
I need help adding this content to the check out guest tab in the employee menu method. I'm new to javafx so if anyone could help me figure this out it would be greatly appreciated! I'm not sure what I am doing wrong or what I need to fix but I'm kind of lost. I've been scouring the web/textbooks for a solution but either I'm missing something big or I haven't come across the solution yet.
i have problem with remove data from line chart. I wrote a program drawing graphs that after the action click on the button completes the chart data.
dataSeries1.getData().removeAll(); <- doesn't work.
Code:
NumberAxis xAxis = new NumberAxis();
xAxis.setLabel("Oś Y");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Oś X");
final LineChart lineChart = new LineChart(xAxis, yAxis);
final XYChart.Series dataSeries1 = new XYChart.Series();
lineChart.setCreateSymbols(false);
lineChart.getData().add(dataSeries1);
Button action:
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int lewy = Integer.parseInt(kresLewy.getText());
int prawy = Integer.parseInt(kresPrawy.getText());
String rownanie = field.getText();
try {
String tekst = lewy + "; " + prawy + "; " + rownanie;
StringReader tekstReader = new StringReader(tekst);
parsery.interpreter.parser parser_obj
= new parsery.interpreter.parser(new parsery.interpreter.MyLexer(tekstReader));
Object result = parser_obj.parse().value;
String sWynik = result.toString();
ZmiennaX zX = new ZmiennaX();
ArrayList<Double> xArr = new ArrayList<Double>();
for (double i = lewy; i <= prawy + 0.001; i = i + zX.getDokladnosc()) // +0.001 dla bledow zaokraglenia
{
xArr.add(zX.round2(i));
}
String sX = xArr.toString();
String wartosciX = sX.substring(1, sX.length() - 1);
String wartosciY = sWynik.substring(1, sWynik.length() - 1);
String XbezSpacji = wartosciX.replace(" ", "");
String YbezSpacji = wartosciY.replace(" ", "");
String[] splitX = XbezSpacji.split(",");
String[] splitY = YbezSpacji.split(",");
dataSeries1.getData().removeAll();
for(int i=0; i<splitX.length; i++){
double x = Double.parseDouble(splitX[i]);
double y = Double.parseDouble(splitY[i]);
dataSeries1.getData().add(new XYChart.Data(x, y));
}
} catch (Exception e) {
System.out.println("Podczs obliczenia wystapil blad. (" + e.getMessage() + ")");
} catch (Error error) {
System.out.println("Podczs obliczenia wystapil blad. (" + error.getMessage() + ")");
}
}
});
Can anyone help me to remove data after drawing a new chart?
removeAll requires elements to be removed passed in its parameter. Since you provided none - nothing gets removed:
dataSeries1.getData().removeAll();
You want to use clear() instead in the line above.
public void clear()
Removes all of the elements from this list (optional operation). The list will be empty after this call returns.
You can use Collections.singleton to remove all data:
dataSeries1.getData().removeAll(Collections.singleton(barChart.getData().setAll()));
See Oracle documentation for Collections.singleton https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html
Good afternoon. I have created an application for an introductory java course that allows a user to sort their DVD collection by title, studio, or year. The application also allows the user to add additional DVD's to their collection, thus enlarging their arrays. The code properly compiles, but there is clearly something wrong as the titles, studio, and years are mixing themselves up. To be clear, this code is from a textbook and is part of a lab that requires the use of the exact methods, packages, etc. that you see in the code. I'm not asking for advice on how to make the code more efficient (although that is welcome as I am learning), but specifically what is wrong with the code provided causing the "scramble". Here is the code I have:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class DVD extends JFrame implements ActionListener
{
// construct components
JLabel sortPrompt = new JLabel("Sort by:");
JComboBox fieldCombo = new JComboBox();
JTextPane textPane = new JTextPane();
// initialize data in arrays
String title[] = {"Casablanca", "Citizen Kane", "Singin' in the Rain", "The Wizard of Oz"};
String studio[] = {"Warner Brothers", "RKO Pictures", "MGM", "MGM"};
String year[] = {"1942", "1941", "1952", "1939"};
// construct instance of DVD
public DVD()
{
super("Classics on DVD");
}
// create the menu system
public JMenuBar createMenuBar()
{
// create an instance of the menu
JMenuBar mnuBar = new JMenuBar();
setJMenuBar(mnuBar);
// construct and populate the File menu
JMenu mnuFile = new JMenu("File", true);
mnuFile.setMnemonic(KeyEvent.VK_F);
mnuFile.setDisplayedMnemonicIndex(0);
mnuBar.add(mnuFile);
JMenuItem mnuFileExit = new JMenu("Exit");
mnuFileExit.setMnemonic(KeyEvent.VK_X);
mnuFileExit.setDisplayedMnemonicIndex(1);
mnuFile.add(mnuFileExit);
mnuFileExit.setActionCommand("Exit");
mnuFileExit.addActionListener(this);
// contruct and populate the Edit menu
JMenu mnuEdit = new JMenu("Edit", true);
mnuEdit.setMnemonic(KeyEvent.VK_E);
mnuEdit.setDisplayedMnemonicIndex(0);
mnuBar.add(mnuEdit);
JMenuItem mnuEditInsert = new JMenuItem("Insert New DVD");
mnuEditInsert.setMnemonic(KeyEvent.VK_I);
mnuEditInsert.setDisplayedMnemonicIndex(0);
mnuEdit.add(mnuEditInsert);
mnuEditInsert.setActionCommand("Insert");
mnuEditInsert.addActionListener(this);
JMenu mnuEditSearch = new JMenu("Search");
mnuEditSearch.setMnemonic(KeyEvent.VK_R);
mnuEditSearch.setDisplayedMnemonicIndex(3);
mnuEdit.add(mnuEditSearch);
JMenuItem mnuEditSearchByTitle = new JMenuItem("by Title");
mnuEditSearchByTitle.setMnemonic(KeyEvent.VK_T);
mnuEditSearchByTitle.setDisplayedMnemonicIndex(3);
mnuEditSearch.add(mnuEditSearchByTitle);
mnuEditSearchByTitle.setActionCommand("title");
mnuEditSearchByTitle.addActionListener(this);
JMenuItem mnuEditSearchByStudio = new JMenuItem("by Studio");
mnuEditSearchByStudio.setMnemonic(KeyEvent.VK_S);
mnuEditSearchByStudio.setDisplayedMnemonicIndex(3);
mnuEditSearch.add(mnuEditSearchByStudio);
mnuEditSearchByStudio.setActionCommand("studio");
mnuEditSearchByStudio.addActionListener(this);
JMenuItem mnuEditSearchByYear = new JMenuItem("by Year");
mnuEditSearchByYear.setMnemonic(KeyEvent.VK_Y);
mnuEditSearchByYear.setDisplayedMnemonicIndex(3);
mnuEditSearch.add(mnuEditSearchByYear);
mnuEditSearchByYear.setActionCommand("year");
mnuEditSearchByYear.addActionListener(this);
return mnuBar;
}
// create the content pane
public Container createContentPane()
{
// populate the JComboBox
fieldCombo.addItem("Title");
fieldCombo.addItem("Studio");
fieldCombo.addItem("Year");
fieldCombo.addActionListener(this);
fieldCombo.setToolTipText("Click the drop-down arrow to display sort fields.");
// construct and populate the north panel
JPanel northPanel = new JPanel();
northPanel.setLayout(new FlowLayout());
northPanel.add(sortPrompt);
northPanel.add(fieldCombo);
// create the JTextPane and center panel
JPanel centerPanel = new JPanel();
setTabsAndStyles(textPane);
textPane = addTextToTextPane();
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(500, 200));
centerPanel.add(scrollPane);
// create Container and set attributes
Container c = getContentPane();
c.setLayout(new BorderLayout(10,10));
c.add(northPanel,BorderLayout.NORTH);
c.add(centerPanel,BorderLayout.CENTER);
return c;
}
// method to create tab stops and set font styles
protected void setTabsAndStyles(JTextPane textPane)
{
// create Tab Stops
TabStop[] tabs = new TabStop[2];
tabs[0] = new TabStop(200, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
tabs[1] = new TabStop(350, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
TabSet tabset = new TabSet(tabs);
// set Tab Style
StyleContext tabStyle = StyleContext.getDefaultStyleContext();
AttributeSet aset =
tabStyle.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.TabSet, tabset);
textPane.setParagraphAttributes(aset, false);
// set Font styles
Style fontStyle =
StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
Style regular = textPane.addStyle("regular", fontStyle);
StyleConstants.setFontFamily(fontStyle, "SansSerif");
Style s = textPane.addStyle("italic", regular);
StyleConstants.setItalic(s, true);
s = textPane.addStyle("bold", regular);
StyleConstants.setBold(s, true);
s = textPane.addStyle("large", regular);
StyleConstants.setFontSize(s, 16);
}
// method to add new text to the JTextPane
public JTextPane addTextToTextPane()
{
Document doc = textPane.getDocument();
try
{
// clear the previous text
doc.remove(0, doc.getLength());
// insert title
doc.insertString(0,"TITLE\tSTUDIO\tYEAR\n",textPane.getStyle("large"));
// insert detail
for (int j = 0; j<title.length; j++)
{
doc.insertString(doc.getLength(), title[j] + "\t", textPane.getStyle("bold"));
doc.insertString(doc.getLength(), studio[j] + "\t", textPane.getStyle("italic"));
doc.insertString(doc.getLength(), year[j] + "\t", textPane.getStyle("regular"));
}
}
catch(BadLocationException ble)
{
System.err.println("Couldn't insert text.");
}
return textPane;
}
// event to process user clicks
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
// user clicks the sort by combo box
if (e.getSource() == fieldCombo)
{
switch(fieldCombo.getSelectedIndex())
{
case 0:
sort(title);
break;
case 1:
sort(studio);
break;
case 2:
sort(year);
break;
}
}
// user clicks Exit on the File menu
if (arg == "Exit")
System.exit(0);
// user clicks Insert New DVD on the Edit Menu
if (arg == "Insert")
{
// accept new data
String newTitle = JOptionPane.showInputDialog(null, "Please enter the new movie's title");
String newStudio = JOptionPane.showInputDialog(null, "Please enter the studio for " + newTitle);
String newYear = JOptionPane.showInputDialog(null, "Please enter the year for " + newTitle);
// enlarge arrays
title = enlargeArray(title);
studio = enlargeArray(studio);
year = enlargeArray(year);
// add new data to arrays
title[title.length-1] = newTitle;
studio[studio.length-1] = newStudio;
year[year.length-1] = newYear;
// call sort method
sort(title);
fieldCombo.setSelectedIndex(0);
}
// user clicks Title on the Search submenu
if (arg == "title")
search(arg, title);
// user clicks Studio on the Search submenu
if (arg == "studio")
search(arg, studio);
// user clicks Year on the Search submenu
if (arg == "year")
search(arg, year);
}
// method to enlarge an array by 1
public String[] enlargeArray(String[] currentArray)
{
String[] newArray = new String[currentArray.length + 1];
for (int i = 0; i<currentArray.length; i++)
newArray[i] = currentArray[i];
return newArray;
}
// method to sort arrays
public void sort(String tempArray[])
{
// loop ton control number of passes
for (int pass = 1; pass < tempArray.length; pass++)
{
for (int element = 0; element < tempArray.length - 1; element++)
if (tempArray[element].compareTo(tempArray[element + 1])>0)
{
swap(title, element, element + 1);
swap(studio, element, element + 1);
swap(year, element, element + 1);
}
}
addTextToTextPane();
}
// method to swap two elements of an array
public void swap(String swapArray[], int first, int second)
{
String hold; // temporary holding area for swap
hold = swapArray[first];
swapArray[first] = swapArray[second];
swapArray[second] = hold;
}
public void search(String searchField, String searchArray[])
{
try
{
Document doc = textPane.getDocument(); // assign text to document object
doc.remove(0,doc.getLength()); // clear previous text
// display column titles
doc.insertString(0,"TITLE\tSTUDIO\tYEAR\n",textPane.getStyle("large"));
// prompt user for search data
String search = JOptionPane.showInputDialog(null, "Please enter the "+searchField);
boolean found = false;
// search arrays
for (int i = 0; i<title.length; i++)
{
if (search.compareTo(searchArray[i])==0)
{
doc.insertString(doc.getLength(), title[i] + "\t", textPane.getStyle("bold"));
doc.insertString(doc.getLength(), studio[i] + "\t", textPane.getStyle("italic"));
doc.insertString(doc.getLength(), year[i] + "\t", textPane.getStyle("regular"));
found = true;
}
}
if (found == false)
{
JOptionPane.showMessageDialog(null, "Your search produced no results.","No results found",JOptionPane.INFORMATION_MESSAGE);
sort(title);
}
}
catch(BadLocationException ble)
{
System.err.println("Couldn't insert text.");
}
}
// main method executes at run time
public static void main(String arg[])
{
JFrame.setDefaultLookAndFeelDecorated(true);
DVD f = new DVD();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setJMenuBar(f.createMenuBar());
f.setContentPane(f.createContentPane());
f.setSize(600,375);
f.setVisible(true);
}
}
Here is a screenshot to give you a sense of what I mean be "scrambled".
Obviously, all of the titles should be in the title column, studios in studio, and years in year.
As always, I appreciate the guidance.
The problem is this line
doc.insertString(doc.getLength(), year[j] + "\t", textPane.getStyle("regular"));
where you put a tab ("\t") after the year but instead you want a newline ("\n"). So the line becomes
doc.insertString(doc.getLength(), year[j] + "\n", textPane.getStyle("regular"));
Do you simply miss a newline after adding the year of a DVD to the document? I.e.
doc.insertString(doc.getLength(), year[j] + "\n", textPane.getStyle("regular"));
I have a problem when I try to crete dynamically Tabs on a JTabbePane by a for. The problem is that I don't know how to access the contents when an event happens.
I will try to show you part of the code to be easy to understand.
conteudoT = new JTabbedPane(JTabbedPane.TOP);
conteudoT.setBounds(5, 19, 477, 232);
for (int i = 0; i < players; i++) {
conteudo = new JPanel();
conteudo.setLayout(null);
Details = new JPanel();
Details.setBounds(15, 11, 307, 183);
Details.setVisible(false);
Details.setName("Details" + i);
conteudo.add(Details);
btnR = new JButton("r");
btnR.addActionListener(this);
conteudoT.addTab("Jogador " + (i + 1), conteudo);
Details.setLayout(new GridLayout(2, 1, 0, 0));
...
contentPane.add(conteudoT);
}
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < players; i++) {
if (e.getSource()==btnR) {
Details.setVisible(true);
}
}
}
What happens here is that the painel Details is added on the last Tab to be constructed and I would like to add it on the Tab that the event happend.
use :
conteudoT.indexOfTab(string)
to get the index. Then use :
conteudoT.getTabComponentAt(int index)
to get the component