I am a beginner in Java, I am trying to build a chatbot. The query and responses are hard coded in 2D string array chatbot[][].
This is the complete code that I have used, Two objects for JTextArea 'input and dialogue ' has been used. Object input has been attached to JPanel and is used to get the text from the user and then this is searched in the 2D string array.If it is found then the response is thrown from the same array.
Now my requirement is when the response is any URL it should be displayed as a link so that user can directly click and go to the site(http://google.com for the current scenario).Kindly suggest how this can be achieved or any modification in code is required. addText is the method that is defined to add entire conversation to dialogue text area which is non editable.
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.lang.Math;
import java.awt.Color;
import java.awt.Toolkit;
public class test implements KeyListener{
JFrame j=new JFrame("Temenos ChatBot");
JPanel p=new JPanel();
JTextArea dialog=new JTextArea(20,50); //it will contain the whole conversation(non editable)
JTextArea input=new JTextArea(1,50); //where we user input our query(editable)
JScrollPane scroll=new JScrollPane(
dialog,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
String[][] chatbot={
{"hi","hello","hola","ola","howdy"}, //check for query
{"hi","hello","hey"}, //provides output of the query
{"google","provide link for google","www.google.com"}, //Query
{"http://google.com"}, //response
//default
{"we can't find your query",
"(Sorry, we could not understand)"}
};
public static void main(String[]args){
new test();
}
private void icon(){
j.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("dy1MzZ-W.png")));//change the icon, paste the icon in default package
}
public test(){
j.setSize(600,400);
j.setResizable(false);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dialog.setEditable(false);
input.addKeyListener(this);
p.add(scroll);
p.add(input);
p.setBackground(new Color(0,150,255));
j.add(p);
j.setVisible(true);
icon();
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(false);
//-----grab quote-----------
String quote=input.getText(); //takes whatever text user is inputting
input.setText("");
addText("->You:\t"+quote);
quote.trim();
while(
quote.charAt(quote.length()-1)=='!' ||
quote.charAt(quote.length()-1)=='.' ||
quote.charAt(quote.length()-1)=='?'
){
quote=quote.substring(0,quote.length()-1);
}
quote.trim();
byte response=0; //byte is data type that will check for response
/*
0:we're searching through chatBot[][] for matches
1:we didn't find anything
2:we did find something
*/
//-----check for matches----
int j=0;//which group we're checking
while(response==0){
if(inArray(quote.toLowerCase(),chatbot[j*2])){
response=2;
int r=(int)Math.floor(Math.random()*chatbot[(j*2)+1].length);
addText("\n->A.I.sha:\t"+chatbot[(j*2)+1][r]);
}
j++;
if(j*2==chatbot.length-1 && response==0){
response=1;
} //if it has come to end then set response to 1
}
//-----default--------------
if(response==1){
int r=(int)Math.floor(Math.random()*chatbot[chatbot.length-1].length);
addText("\n->A.I.sha:\t"+chatbot[chatbot.length-1][r]);
}
addText("\n");
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_ENTER){
input.setEditable(true);
}
}
public void keyTyped(KeyEvent e){}
public void addText(String str){
dialog.setText(dialog.getText()+str);
}//it will add whatever text dialogue box is having
public boolean inArray(String in,String[] str){
boolean match=false;
for(int i=0;i<str.length;i++){
if(str[i].equals(in)){
match=true;
} //Searches for string 'in' in string array,if it finds return true
}
return match;
}
}
If you're making a GUI in swing, you could follow another stack overflow answer, such as this one
How to add hyperlink in JLabel
Or, you could just have java open the browser to that webpage:
// Create Desktop object
Desktop d=Desktop.getDesktop();
// Browse a URL, say google.com
d.browse(new URI("http://google.com"));
You can use the parse static method from Uri
Uri myUri = Uri.parse("http://google.com")
Related
I have two buttons on an applet and a variable "stat". The idea is that I want to change a value of the variable by either pressing button plus or minus that will add or subtract 1, respectively. But the variable "stat" does not change its value in any way. Can you please help me understand in what way can I overwrite a value of the variable?
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class test extends Applet implements ActionListener
{
int stat=0;
Button plus, minus;
String str="";
public void init()
{
plus = new Button("+");
plus.setActionCommand("+");
minus = new Button("-");
minus.setActionCommand("-");
minus.addActionListener(this);
plus.addActionListener(this);
add(plus);
add(minus);
}
public void actionPerformed(ActionEvent ae)
{
str = ae.getActionCommand();
if (str.equals("minus")) { stat-=1; }
else if (str.equals("plus")) { stat+=1; }
}
}
First off, this is my first post to Stack Overflow so please forgive me if I am not following some of the proper etiquitte. Im trying to make a GUI program that will display different food genres and then when the user presses the genre they want it will show a randomly generated restraunt of that genre. I am fairly new to programming and I am having a hard time figuing out how to make my buttons actually work. I have assigned the Restraunts objects each a value. Mexican will be values 1 and 2. Italian will be values 3 and 4. What Im wanting is when the user selects "Mexican" for the program to generate a random number (the restraunts value attribute) between 1 and 2 and then display that object with all its attributes in the same window. I've been stuck on this part for a bit and any help would be greatly appreciated. Thank you all in advance for your time. The code I have is as follows:
import TrySource.TryWindow;
import TrySource.Restraunts;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class TrySomethingNew
{
public static void main (String[] args)
{
TryWindow frame = new TryWindow();
frame.setTitle("Try Something New");
frame.setSize(1000,900);
frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
package TrySource;
import TrySource.TryWindow.ButtonClicked;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class TryWindow extends JFrame
{
JButton jbtMexican = new JButton("Mexican");
JButton jbtItalian = new JButton("Italian");
public TryWindow()
{
super("Try Something New");
add(jbtMexican);
add(jbtItalian);
}//end TryWindow constructor
class ButtonClicked implements MouseListener
{
#Override
public void mouseClicked(MouseEvent e)
{
}
#Override
public void mousePressed(MouseEvent e)
{
}
#Override
public void mouseReleased(MouseEvent e)
{
}
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
}
}//end class
package TrySource;
public class Restraunts
{
String restrauntName;
String restrauntAddress;
String restrauntPhone;
public Restraunts(String name, String address, String phone, int value)
{
restrauntName = name;
restrauntAddress = address;
restrauntPhone = phone;
}//end constructor
Restraunts joseLocos = new Restraunts("Jose Locos", "853 N Glenstone Ave, Springfield, MO 65802",
"(417) 831-1300", 1);
Restraunts amigos = new Restraunts ("Amigos Mexican Restaurant","2118 S Campbell Ave, Springfield, MO 65807",
"(417) 887-1401", 2);
Restraunts zios = new Restraunts("Zios Italian Kitchen", "1249 E Kingsley St, Springfield, MO 65804",
"(417) 889-1919", 3);
Restraunts bambinos = new Restraunts("Bambinos Cafe", "1141 E Delmar St, Springfield, MO 65807",
"(417) 862-9999", 4);
}//end Restraunts
Add the Restraunts to a List
Group them together (by their type) using a Map
Use Collections.shuffle to randomise the List and select the first one
Take a look at
Collections Trail
How to Use Buttons, Check Boxes, and Radio Buttons
How to Write an Action Listeners
for more details
Oh, and you might like to gave a look at How to Use CardLayout
When the text in JLabel is too long there are visible 3 dots at the end of text. Is it possible to put them at the beginning?
You may consider using FontMetrics. class to see the length of your text under the current font.
_________________________________
|
| This is some really long text that I want to fit in the small label
|________________________________
^^^ YOUR LABEL ^^^
Say you want to fit that long text into that label.
Here is what you can do (and this is just a wild guess and I am making this on the fly)
Start with your three dots ... in a String.
Start adding appending characters to it, one by one.
Get the width of your JLabel.
Use FontMetrics to measure the length of your text , in pixels, as you append more characters
Keep adding more characters as long as the pixel length of the text is less than the width of your JLabel
Once it becomes greater than the width of the JLabel, get out of the loop.
Set this newly formed text as the text of your JLabel
You should end up like this:
_________________________________
|
| ...This is some really long tex
|________________________________
^^^ YOUR LABEL ^^^
Here is an easy way to get started with FontMetrics. Avoid the bickering there. Just do what the accepted answer says: Java: Friendlier way to get an instance of FontMetrics
SSCCE is in accordance with what the OP really wants rather than what I explained
package stack;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class BackwardsDots extends JFrame{
JLabel label = new JLabel(){
#Override
public Dimension getPreferredSize(){
return new Dimension(200,100);
}
};
String text = "This is a design requirement and not my whim";
FontMetrics fm;
Font theFontBeingUsed;
//--------------------------------------------------------------------------------
public BackwardsDots(){
getContentPane().add(label);
pack();
theFontBeingUsed = new Font("Ubuntu",Font.BOLD,14);
fm = Toolkit.getDefaultToolkit().getFontMetrics(theFontBeingUsed);
label.setText(trimmedStringCalculator(text));
label.setToolTipText(text);
label.setBorder(BorderFactory.createDashedBorder(Color.RED));
label.addComponentListener(new ComponentListener(){
#Override
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentResized(ComponentEvent arg0) {
label.setText(trimmedStringCalculator(text));
}
#Override
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
});
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//--------------------------------------------------------------------------------
private String trimmedStringCalculator(String inputText){
String ellipses = "...";
String textToBeDisplayed = "";
int widthOfJLabel = label.getWidth();
for(int i = text.length()-1; i >= 0; i--){
if(fm.stringWidth(ellipses + textToBeDisplayed) <= widthOfJLabel){
textToBeDisplayed = text.charAt(i) + textToBeDisplayed;
}
}
String finalText;
if(textToBeDisplayed.equals(inputText)){
finalText = inputText;
}else{
finalText = ellipses.concat(textToBeDisplayed);
}
return finalText;
}
//--------------------------------------------------------------------------------
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
new BackwardsDots();
}
});
}
}
Output
I have another solution, that relies on LabelUI. First the code:
LabelUI labelUI = new MetalLabelUI() {
#Override
protected String layoutCL(JLabel label, FontMetrics fontMetrics, String text, Icon icon, Rectangle viewR, Rectangle iconR, Rectangle textR) {
String clipString = "...";
// Use reversed text, because first characters may be larger or thinner than last ones.
String reversedText = new StringBuilder(text).reverse().toString();
// Let Swing do its magic.
String result = super.layoutCL(label, fontMetrics, reversedText, icon, viewR, iconR, textR);
// Not using .equals is intentional. Previous method will return a different instance
// if and only if a clip operation occurred.
if (result != text) {
// Use the same character count, but starting with the end.
result = clipString
+ text.substring(text.length() - result.length() + clipString.length());
} else {
// Restore the original
result = text;
}
return result;
}
};
The goal is to let Swing compute everything, including its clipped string, and using this as a hint to perform our own left clipping.
The trick is that we have to provide the reversed string to the super method, since our result will clip leading characters, we need to be sure that the computation was right. Characters have different widths.
The main advantage for me is that there is a very little overhead, compared to the current solution that compute a new size before the UI, and the UI will start doing the same.
EDIT: Change code to restore the original string when not clipped.
I think this is rather a system behaviour, more than JLabel's, so you couldn't really do that.
Actually, i have already ask this question in here. But, i'm making mistake. I haven't already get the solution.
First, at the question before, i can get Rectangle with
Rectangle rectangle = textArea.modelToView( textArea.getCaretPostion() );
I'm also get X and Y position.
I'm creating a editor that can add new Text Area each i press Enter key. XY position with code above always give same return in every Text Area. Look my code.
import java.awt.Container;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
public class forquestion extends JFrame {
Container textAreaBox;
LinkedList<JTextComponent> textArea;
int nameTA;
public forquestion() {
int nameTA = 0;
textArea = new LinkedList<>();
textAreaBox = Box.createVerticalBox();
textAreaBox.add(Box.createVerticalGlue());
addLine();
this.add(textAreaBox);
this.setVisible(true);
}
public static void main(String[] args) {
forquestion app = new forquestion();
app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void addLine () {
JTextComponent temp_ta = createTextComponent();
textArea.add(temp_ta);
textAreaBox.add(textArea.getLast());
textAreaBox.add(Box.createVerticalGlue());
}
protected JTextComponent createTextComponent() {
JTextArea ta = new JTextArea("test");
/*if (count%2==0)
ta.setForeground(Color.red);
else
ta.setForeground(Color.GREEN);*/
ta.setFont(new Font("Courier New",Font.PLAIN,16));
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setName(Integer.toString(nameTA));
nameTA+=1;
basicKey("ENTER", enter, ta);
ta.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent ev) {
try {
taMousePressed(ev);
} catch (BadLocationException ex) {
Logger.getLogger(forquestion.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
return ta;
}
public void basicKey(String s, Action a, JTextArea ta) {
ta.getInputMap().put(KeyStroke.getKeyStroke(s), s);
ta.getActionMap().put(s, a);
}
Action enter = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
addLine();
}
};
private void taMousePressed(java.awt.event.MouseEvent ev) throws BadLocationException {
int now_focus = Integer.parseInt(ev.getComponent().getName());
int _caret;
_caret = textArea.get(now_focus).getCaretPosition();
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
double x = rectangle.getX();
//int xc = textArea.get(now_focus).getLocation().x;
double y = rectangle.getY();
//int yc = textArea.get(now_focus).getLocation().y;
//double h = rectangle.getHeight();
//double w = rectangle.getWidth();
System.out.println(x);
System.out.println(y);
//System.out.println(xc);
//System.out.println(yc);
//System.out.println(h);
//System.out.println(w);
System.out.println("");
}
}
My code will print XY position each time you press a Text Area. But, the display always same in every text area. (Try to make many Text Area and give some text) Btw, it just simple code. You need change the window frame size for update the new text area after you press enter key..hahaha.
So, my question is: How can i get the XY position of caret (text cursor) in any Text Area. I want to display JPopmenu there. :)
I hope this question clear for you. Thx before.
The Rectangle reported back is relative to the text area, where it's 0x0 position is the top, left corner of the component.
If you use something like...
popup.show(textArea.get(now_focus), rectangle.x, rectangle.y + rectangle.height);
Where popup is a JPopupMenu, it will make the required translations to the screen itself.
Now. Having said that. Personally, I would prefer to use the popup API support provided by Swing. This is going to mean needing to create a custom component that extends from JTextArea to achieve it...
public class MyPopupTextArea extends JTextArea {
/*...*/
public Point getPopupLocation(MouseEvent evt) {
Rectangle rectangle = textArea.get(now_focus).modelToView(_caret);
Point p = rectangle.getLoction();
p.y += rectangle.height;
return p;
}
}
Then, based on your needs, you can use setComponentPopup to provide a shared instance of the JPopupMenu or, if required, create a custom JPopupMenu for each instance of the custom editor and use setComponentPopup as you see fit...no messing about with mouse listeners ;)
Working on a project I got into running java applications through a small console-like window. Thanks to the wonderful community in here I managed to solve the problem with outputting the data from a proccess but my command-line applications running will constantly give errors as there is no input stream.
Based on the last helpful reply in that thread I suppose I shall approach similarly the JTextFieldInputStream extends InputStream implementation, but looking in the javadocs and throughout google and the internet for some class that does just that I really found nothing explaining how to do this.
So I am asking for some link, example, tutorial, sample code for it just like in the previous topic.
Give me just a class that extends InputStream and can be extended to read from a JTextField when I press Enter and I will do the rest with implementing this and making it work! Thanks in advance!
What I don't understand if why you need a JTextField that extends InputStream? Basically, what you are looking for is:
Add an ActionListener on the JTextField (ie, when use presses Enter, actionPerformed will be invoked)
You need to grab the text of the JTextField using getText()
You can then "transform" the String text to an InputStream with new ByteArrayInputStream(text.getBytes("UTF-8"));
Here is a small snippet that should get you the basic idea:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestTextField {
private void initUI() {
JFrame frame = new JFrame(TestTextField.class.getSimpleName());
frame.setLayout(new FlowLayout());
final JTextField textfield = new JTextField(20);
textfield.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
String text = textfield.getText();
InputStream is = new ByteArrayInputStream(text.getBytes("UTF-8"));
// Here do something with your input stream (something non-blocking)
System.err.println(text);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(textfield);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTextField().initUI();
}
});
}
}
How about this implementation
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JTextField;
public class JTextFieldInputStream extends InputStream {
byte[] contents;
int pointer = 0;
public JTextFieldInputStream(final JTextField text) {
text.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyChar()=='\n'){
contents = text.getText().getBytes();
pointer = 0;
text.setText("");
}
super.keyReleased(e);
}
});
}
#Override
public int read() throws IOException {
if(pointer >= contents.length) return -1;
return this.contents[pointer++];
}
}
to use this input stream, do the following
InputStream in = new JTextFieldInputStream( someTextField );
char c;
while( (c = in.read()) != -1){
//do whatever with c
}
does it read only when I hit enter?
it reads when you call in.read() if the return value -1 it means end of the stream
(And will I be able to modify so that the Enter key empties the JTextField?)
you need to add an action listener and this functionality has nothing to do with the job of input stream