I'm trying to quickly highlight my specific text in JTextArea. The code I need is running too slow, and I would like to know if there is a faster way to highlight text without crashing the whole application.
I have over 5000 words to scroll through and see if there is a need to highlight them or not, but this code doesn't work great for me. I'm looking for a better way to do it. This is my code:
class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter
{
public MyHighlightPainter(Color color) {
super(color);
}
}
Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.yellow);
public void Highligh(JTextComponent textComp, String pattern)
{
try {
Highlighter hilite = textComp.getHighlighter();
Document doc = textComp.getDocument();
String text = doc.getText(0, doc.getLength());
for(int pos = 0; (pos=text.toUpperCase().indexOf(pattern.toUpperCase(),pos))>=0; pos += pattern.length())
hilite.addHighlight(pos, pos+pattern.length(), myHighlightPainter);
} catch (Exception e) {}
}
public void keyReleased(KeyEvent arg0) {
String text = vocabolario.getText();
String[] parziale = new String[5000];
try {
String p1 = "SELECT definizione FROM Cherubini WHERE definizione LIKE '%", p2 = "%';", px = vocabolario.getText(), query = p1+px+p2;
ResultSet rs = Main.conn().createStatement().executeQuery(query);
while(rs.next())
{
String[] dati = { rs.getString("definizione") };
for(int i = 0; i < dati.length; i++) { parziale[i] = dati[i]; textArea.append(parziale[i]+"\n"); }
}
}
catch(SQLException exc) {}
Highligh(textArea,vocabolario.getText());
}
});
for(int pos = 0; (pos=text.toUpperCase().indexOf(pattern.toUpperCase(),pos))>=0; pos += pattern.length())
Why do you keep converting the data to upper case? This should only be done once:
String upperText = text.toUpperCase();
String upperPattern = pattern.toUpperCase();
for(int pos = 0; (pos = upperText.indexOf(upperPattern, pos)) >= 0; pos += pattern.length())
Related
I have a csv file, after I overwrite 1 line with the Write method, after re-writing to the file everything is already added to the end of the file, and not to a specific line
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
using System.Text;
using System.IO;
public class LoadQuestion : MonoBehaviour
{
int index;
string path;
FileStream file;
StreamReader reader;
StreamWriter writer;
public Text City;
public string[] allQuestion;
public string[] addedQuestion;
private void Start()
{
index = 0;
path = Application.dataPath + "/Files/Questions.csv";
allQuestion = File.ReadAllLines(path, Encoding.GetEncoding(1251));
file = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
writer = new StreamWriter(file, Encoding.GetEncoding(1251));
reader = new StreamReader(file, Encoding.GetEncoding(1251));
writer.AutoFlush = true;
List<string> _questions = new List<string>();
for (int i = 0; i < allQuestion.Length; i++)
{
char status = allQuestion[i][0];
if (status == '0')
{
_questions.Add(allQuestion[i]);
}
}
addedQuestion = _questions.ToArray();
City.text = ParseToCity(addedQuestion[0]);
}
private string ParseToCity(string current)
{
string _city = "";
string[] data = current.Split(';');
_city = data[2];
return _city;
}
private void OnApplicationQuit()
{
writer.Close();
reader.Close();
file.Close();
}
public void IKnow()
{
string[] quest = addedQuestion[index].Split(';');
int indexFromFile = int.Parse(quest[1]);
string questBeforeAnsver = "";
for (int i = 0; i < quest.Length; i++)
{
if (i == 0)
{
questBeforeAnsver += "1";
}
else
{
questBeforeAnsver += ";" + quest[i];
}
}
Debug.Log("indexFromFile : " + indexFromFile);
for (int i = 0; i < allQuestion.Length; i++)
{
if (i == indexFromFile)
{
writer.Write(questBeforeAnsver);
break;
}
else
{
reader.ReadLine();
}
}
reader.DiscardBufferedData();
reader.BaseStream.Seek(0, SeekOrigin.Begin);
if (index < addedQuestion.Length - 1)
{
index++;
}
City.text = ParseToCity(addedQuestion[index]);
}
}
There are lines in the file by type :
0;0;Africa
0;1;London
0;2;Paris
The bottom line is that this is a game, and only those questions whose status is 0, that is, unanswered, are downloaded from the file. And if during the game the user clicks that he knows the answer, then there is a line in the file and is overwritten, only the status is no longer 0, but 1 and when the game is repeated, this question will not load.
It turns out for me that the first question is overwritten successfully, and all subsequent ones are simply added at the end of the file :
1;0;Africa
0;1;London
0;2;Paris1;1;London1;2;Paris
What's wrong ?
The video shows everything in detail
This is my code which I am using but when I am trying to print dataArray object, then data is not show in JTable. Which model properties of table to print Object array values can used and how?
public class ShowAddressForm extends javax.swing.JFrame {
Object data[][];
Object dataArray[][];
int count = 0;
String st;
public ShowAddressForm(String fname , String str) {
super(fname);
st = str;
initComponents();
fillTable();
}
public void fillTable()
{
int count = 0;
String str;
try
{
BufferedReader br = new BufferedReader(new FileReader("D:\\JavaPrograms\\Contact Management System\\InputFiles\\AddressFile"));
while((str = br.readLine()) != null)
{
count++;
}
br.close();
} catch (Exception e)
{
}
Object id;
Object name;
data = new Object[count][7];
int i = 0 , j = 0 , m;
try
{
BufferedReader buffrea = new BufferedReader(new FileReader("D:\\JavaPrograms\\Contact Management System\\InputFiles\\AddressFile"));
while((str = buffrea.readLine()) != null)
{
StringTokenizer token = new StringTokenizer(str , "*");
int n = token.countTokens();
id = token.nextElement();
name = token.nextElement();
String strNameLow = name.toString().toLowerCase();
String strNameUpp = name.toString().toUpperCase();
if(strNameLow.startsWith(st.toLowerCase()) || strNameUpp.startsWith(st.toUpperCase()))
{
data[i][0] = id;
data[i][1] = name;
for(j = 2 ; j < n ; j++)
{
data[i][j] = token.nextElement();
}
i = i + 1;
}
}
buffrea.close();
} catch(IOException ioe){
System.out.println("Error : " + ioe.toString());
}
dataArray = new Object[i][7];
for(int a = 0 ; a < i ; a++)
{
for(int b = 0 ; b < 7 ; b++)
{
dataArray[a][b] = data[a][b];
}
}
//Here is the code to print dataArray object which i used but it is not working, when i am run my program it is print "[Ljava.lang.Object;#1cc2e30" in table's first cell[0][0] position
DefaultTableModel model = (DefaultTableModel)this.data_table.getModel();
model.addRow(dataArray);
}
I filled data in a JTable like this. You might want to give it a try adapting it to your code. Variable and stuff are in spanish, just replace them with what you need. In my case it's a table with 4 columns representing a date, a score, duration and max viewers.
private void fillJTable(){
//creating data to add into the JTable. Here you might want to import your proper data from elsewhere
Date date = new Date();
UserReplay rep1 = new UserReplay(date, 12, 13,14);
UserReplay rep2 = new UserReplay(date, 2,34,5);
ArrayList<UserReplay> usuaris = new ArrayList<>();
usuaris.add(rep1);
usuaris.add(rep2);
//----Filling Jtable------
DefaultTableModel model = (DefaultTableModel) view.getTable().getModel();
model.addColumn("Fecha");
model.addColumn("Puntuación");
model.addColumn("Tiempo de duración");
model.addColumn("Pico máximo de espectadores");
for (int i = 0; i < usuaris.size(); i++){
Vector<Date> fecha = new Vector<>(Arrays.asList(usuaris.get(i).getDate()));
Vector<Integer> puntuacion = new Vector<>(Arrays.asList(usuaris.get(i).getPuntuacion()));
Vector<Integer> tiempo = new Vector<>(Arrays.asList(usuaris.get(i).getTiempo()));
Vector<Integer> espectadors = new Vector<>(Arrays.asList(usuaris.get(i).getTiempo()));
Vector<Object> row = new Vector<Object>();
row.addElement(fecha.get(0));
row.addElement(puntuacion.get(0));
row.addElement(tiempo.get(0));
row.addElement(espectadors.get(0));
model.addRow(row);
}
}
I am working on a driving licence project on j2Me wich is including Tests like quizz , well and i am having a problem after parsing the questions and moving them into choiceGroups just like that :
if (questions.length > 0) {
for (int i = 0; i < questions.length; i++) {
ChoiceGroup reponses = new ChoiceGroup("Reponses" + i, Choice.EXCLUSIVE);
reponses.append(questions[i].getReponse1(), null);
reponses.append(questions[i].getReponse2(), null);
reponses.append(questions[i].getReponse3(), null);
pass.append(questions[i].getContenu());
pass.append(reponses);
}
}
} catch (Exception e) {
System.out.println("Exception:" + e.toString());
}
disp.setCurrent(pass);
and the next step is the command who's controlling the choiceGroups to test them if they are like the true answer or not .
so i am blocked here .
if (c == valider) {
int result = 0;
for (int i = 0; i < pass.size(); i++) {
String ch = pass.get(i).getLabel();
System.out.println(ch);
}
}
I don't know how to get the choice from the choicegroup
any help
Actually, I am not sure what totally you want for:
This code will help you get selected items from choicegroup that i did long time before:
//get a selected array in choicegroup
private String[] choiceGroupSelected(ChoiceGroup cg) {
String selectedArray[] = new String[cg.size()];
int k = 0;
for (int i = 0; i < cg.size(); i++) {
if (cg.isSelected(i)) {
selectedArray[k] = cg.getString(i);
k++;
}
}
return selectedArray;
}
That function will help me get all selected items for deleting action below:
private void deleteSpecificItem() {
try {
String temp = null;
int index;
//get ChoiceGroup size
int numbers = cgTrip.size();
String selectedItems[] = choiceGroupSelected(cgTrip);
//
rs = services.RecordStoreManager.openRecordStoreByName("TripRS");
re = rs.enumerateRecords(null, null, true);
String[] tripList = new String[2];
for (int i = 0; i < numbers; i++) {
temp = selectedItems[i];
if (temp != null) {
while (re.hasNextElement()) {
try {
index = re.nextRecordId();
System.out.println("RecordID: " + index);
byte[] byteBuff = rs.getRecord(index);
String source = new String(byteBuff);
tripList = services.StringManager.getItems(source, ";", 2);
String strProcess = tripList[0] + "-" + tripList[1];
//inspect all of items in choicegroup and if they are selecting then compare with record
//If comparison is true then delete this record
if (temp.equals(strProcess)) {
System.out.println("Delete RecordID: " + index);
rs.deleteRecord(index);
re.keepUpdated(true);
break;
}
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
}
}
try {
rs.closeRecordStore();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
rs = null;
re.destroy();
this.LoadTripItem();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
}
}
This code replaces the selected words with the new ones like this:
String search = jTextField1.getText();
String replaced = jTextPane.getText().replace(search, jTextField2.getText());
jTextPane.setText(replaced);
What is the easiest way to set the backgrounds of the new words to yellow?
You can use attributes:
Simple AttributeSet changed = new SimpleAttributeSet();
StyleConstants.setForeground(changed, Color.RED);
StyleConstants.setBackground(changed, Color.YELLOW);
// Change attributes on some text
StyledDocument doc = textPane.getStyledDocument();
doc.setCharacterAttributes(20, 4, changed, false);
For find/replace logic check out: Find/Replace, Highlight Words. You would modify the highlighting code to use the attributes.
private void changeAllActionPerformed(java.awt.event.ActionEvent evt) {
int j = 0;
int i = 0;
int index = 0;
String search = jTextField1.getText();
String replaced = jTextPane.getText().replace(search, jTextField2.getText());
jTextPane.setText(replaced);
String newtext = jTextField2.getText();
try{
if(!jTextField2.getText().isEmpty()){
while(i != -1){
i = jTextPane.getText().indexOf(newtext, j);
if(i == -1)
break;
if(evt.getSource() == changeAll|| evt.getSource() == changeAllButton){
jTextPane.select(i, i + newtext.length());
}
Color c = Color.YELLOW;
Style s = jTextPane.addStyle("TextBackground", null);
StyleConstants.setBackground(s, c);
StyledDocument d = jTextPane.getStyledDocument();
d.setCharacterAttributes(jTextPane.getSelectionStart(), jTextPane.getSelectionEnd() - jTextPane.getSelectionStart(), jTextPane.getStyle("TextBackground"), false);
j = i + search.length();
index++;
}
if (index > 0){
jTextPane.grabFocus();
jTextPane.setCaretPosition(jTextPane.getText().indexOf(newtext, 0) );
}
} catch (Exception e){
jLabel.setText("error");
System.err.print(e);
}
I have a big String (XML Style) and I provide a text-field for capturing the words to search. All words found should be highlighted.
The problem i have is, that the words can appear multiple times in that String but only the first/or last word is highlighted.
I found out that the problem is that the selectionStart and ending is always the same.
Can u help me ?
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
String CurrentText = textPane.getText();
StringReader readtext;
BufferedReader readBuffer;
int i = 0;
int matches = 0;
readtext = new StringReader(CurrentText);
readBuffer = new BufferedReader(readtext);
String line;
try {
i = CurrentText.indexOf(textToFind);
int start = 0;
int end = 0;
Pattern p = Pattern.compile(textToFind);
while ((line = readBuffer.readLine()) != null) {
Matcher m = p.matcher(line);
// indicate all matches on the line
while (m.find()) {
matches++;
while (i >= 0) {
textPane.setSelectionStart(i);
textPane.setSelectionEnd(i + textToFind.length());
i = CurrentText.indexOf(textToFind, i + 1);
start = textPane.getSelectionStart();
end = textPane.getSelectionEnd();
try {
highlighter.addHighlight(start, end,
myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
JOptionPane.showMessageDialog(paneXML,
matches+" matches have been found", "Matched",
JOptionPane.INFORMATION_MESSAGE);
}
You have a LOT of redundant code. Here's a short and sweet solution using String.indexOf
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
textToFind = textToFind.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
String currentText = textPane.getText(); //UPPERCASE LOCALS ARE EVIL
currentText = currentText.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
int offset = 0;
for(int index = currentText.indexOf(textToFind, offset); index >= 0; index = currentText.indexOf(textToFind, offset)){
int startIndex = currentText.indexOf(textToFind, offset);
int endIndex = startIndex + textToFind.length() - 1; //this gets you the inclusive endIndex.
textPane.setSelectionStart(startIndex);
textPane.setSelectionEnd(endIndex);
offset = startIndex + 1; //begin the NEXT search at startIndex + 1 so we don't match the same string over and over again
System.out.println(startIndex);
System.out.println(endIndex);
try {
highlighter
.addHighlight(startIndex, endIndex, myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}