Currently, I am working on a program with python and PYQT5 where user inputs have to be only numbers. The problem is that I have no idea how to do it. For example when I get this variable
VAR_1=float(self.ui.lineEdit.text())
I need that the text entered is only a number. i mean when the user is trying to write a letter o symbol nothing happens.
Use/Try setValidator or setInputMask methods
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class ButtonName(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Example - Validator")
self.setGeometry(800, 200, 200, 200)
self.UI()
self.layouts()
self.show()
def UI(self):
self.lbl_integer = QLabel("Integer Validator")
self.textbox_integervalidator = QLineEdit()
self.textbox_integervalidator.setPlaceholderText("upto 3 digit value only accept")
self.textbox_integervalidator.setValidator(QIntValidator(1, 999, self))
self.lbl_double = QLabel("Double Validator")
self.textbox_doublevalidator = QLineEdit()
self.textbox_doublevalidator.setValidator(QDoubleValidator(0.99, 99.99, 2))
self.lbl_regexp = QLabel("RexExp Validator")
self.textbox_regexpvalidator = QLineEdit()
reg_ex_1 = QRegExp("[0-9]+.?[0-9]{,2}") # double
# reg_ex_2 = QRegExp("[0-9]{1,5}") # minimum 1 integer number to maxiumu 5 integer number
# reg_ex_3 = QRegExp("-?\\d{1,3}") # accept negative number also
# reg_ex_4 = QRegExp("")
self.textbox_regexpvalidator.setValidator(QRegExpValidator(reg_ex_1))
def layouts(self):
mainlayout = QVBoxLayout()
mainlayout.addWidget(self.lbl_integer)
mainlayout.addWidget(self.textbox_integervalidator)
mainlayout.addWidget(self.lbl_double)
mainlayout.addWidget(self.textbox_doublevalidator)
mainlayout.addWidget(self.lbl_regexp)
mainlayout.addWidget(self.textbox_regexpvalidator)
self.setLayout(mainlayout)
def main():
app = QApplication(sys.argv)
mainwindow = ButtonName()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
try make a mask for your line edit:
self.lineEdit.setInputMask("00")
When you put "0" in Mask, the code will understand that it can only be numbers. The amount of zero placed will be the amount of houses that the lineedit will accept. In this case how and "00" the lineEdit accepted two houses (the ten's houses)
You can try it like this
self.ui.lineEdit.textChanged.connect(self.accept_only_numbers)
def accept_only_numbers(self):
VAR_1=float(self.ui.lineEdit.text())
if VAR_1.isnumeric() == True:
print("ok is number")
else:
VAR_1.clear()
Related
I'm at an impasse with this little project. I have a calculator with buttons for basic operations, a screen, and a history showing the previous numbers in the expression. As far as I can tell, I need to make the calculator's screen and history global so I can access them from the calculator's button's methods.
Here's the unfinished but functioning code, this is 99% GUI:
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QLineEdit
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import *
class Calculator(QWidget):
def __init__(self):
super().__init__()
# All our buttons are here
zero = QPushButton("0")
one = QPushButton("1")
two = QPushButton("2")
three = QPushButton("3")
four = QPushButton("4")
five = QPushButton("5")
six = QPushButton("6")
seven = QPushButton("7")
eight = QPushButton("8")
nine = QPushButton("9")
plus = QPushButton("+")
minus = QPushButton("-")
times = QPushButton("*")
divide = QPushButton("/")
dot = QPushButton(".")
equals = QPushButton("=")
# User's history will appear above the screen
history = QLabel()
# Creating a Regex validator to limit inputs to numbers and appropriate symbols
regex = QRegExp("\\d*(?:\\.\\d+)?")
num_validator = QRegExpValidator(regex)
# Screen is a one line text box using the above Regex validator
screen = QLineEdit()
screen.setAlignment(Qt.AlignRight)
screen.setValidator(num_validator)
# The calculator has a four column layout
first_col = QVBoxLayout()
second_col = QVBoxLayout()
third_col = QVBoxLayout()
fourth_col = QVBoxLayout()
# Creating Layout
zero_and_divide_container = QHBoxLayout()
button_container = QHBoxLayout()
screen_and_button_container = QVBoxLayout()
first_col.addWidget(seven)
first_col.addWidget(four)
first_col.addWidget(one)
second_col.addWidget(eight)
second_col.addWidget(five)
second_col.addWidget(two)
third_col.addWidget(nine)
third_col.addWidget(six)
third_col.addWidget(three)
fourth_col.addWidget(plus)
fourth_col.addWidget(minus)
fourth_col.addWidget(times)
button_container.addLayout(first_col)
button_container.addLayout(second_col)
button_container.addLayout(third_col)
button_container.addLayout(fourth_col)
zero_and_divide_container.addWidget(dot)
zero_and_divide_container.addWidget(zero)
zero_and_divide_container.addWidget(equals)
zero_and_divide_container.addWidget(divide)
screen_and_button_container.addWidget(history)
screen_and_button_container.addWidget(screen)
screen_and_button_container.addLayout(button_container)
screen_and_button_container.addLayout(zero_and_divide_container)
self.setLayout(screen_and_button_container)
self.show()
def main():
app = QApplication([])
calc = Calculator()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
This does what it's supposed to. However, as stated before, I need to make the screen and history global so the button methods can access their contents. When I try to do that in the simplest way, by just moving the history and screen out of the method, like so:
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QLineEdit
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import *
class Calculator(QWidget):
# Screen will appear above buttons
screen = QLineEdit()
# User's history will appear above the screen
history = QLabel()
def __init__(self):
super().__init__()
zero = QPushButton("0")
one = QPushButton("1")
two = QPushButton("2")
three = QPushButton("3")
four = QPushButton("4")
five = QPushButton("5")
six = QPushButton("6")
seven = QPushButton("7")
eight = QPushButton("8")
nine = QPushButton("9")
plus = QPushButton("+")
minus = QPushButton("-")
times = QPushButton("*")
divide = QPushButton("/")
dot = QPushButton(".")
equals = QPushButton("=")
# Creating a Regex validator to limit inputs to numbers and appropriate symbols
regex = QRegExp("\\d*(?:\\.\\d+)?")
num_validator = QRegExpValidator(regex)
# Screen is a one line text box using the above Regex validator
self.screen.setAlignment(Qt.AlignRight)
self.screen.setValidator(num_validator)
# The calculator has a four column layout
first_col = QVBoxLayout()
second_col = QVBoxLayout()
third_col = QVBoxLayout()
fourth_col = QVBoxLayout()
# Creating Layout
zero_and_divide_container = QHBoxLayout()
button_container = QHBoxLayout()
screen_and_button_container = QVBoxLayout()
first_col.addWidget(seven)
first_col.addWidget(four)
first_col.addWidget(one)
second_col.addWidget(eight)
second_col.addWidget(five)
second_col.addWidget(two)
third_col.addWidget(nine)
third_col.addWidget(six)
third_col.addWidget(three)
fourth_col.addWidget(plus)
fourth_col.addWidget(minus)
fourth_col.addWidget(times)
button_container.addLayout(first_col)
button_container.addLayout(second_col)
button_container.addLayout(third_col)
button_container.addLayout(fourth_col)
zero_and_divide_container.addWidget(dot)
zero_and_divide_container.addWidget(zero)
zero_and_divide_container.addWidget(equals)
zero_and_divide_container.addWidget(divide)
screen_and_button_container.addWidget(self.history)
screen_and_button_container.addWidget(self.screen)
screen_and_button_container.addLayout(button_container)
screen_and_button_container.addLayout(zero_and_divide_container)
self.setLayout(screen_and_button_container)
self.show()
def main():
app = QApplication([])
calc = Calculator()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The window never opens and I get exit code -1073740791 (0xC0000409). What am I doing wrong here?
I recommend you run your code from the terminal to get a more explanatory error message, in your case I get:
QWidget: Must construct a QApplication before a QWidget
Aborted (core dumped)
And there the error is pointed out, QWidget must be created after QApplication but in your case they are created before, also I do not see any advantage in that they are variables of the class instead of attributes.
The solution is to move it to:
# ...
class Calculator(QWidget):
def __init__(self):
super().__init__()
# Screen will appear above buttons
self.screen = QLineEdit()
# User's history will appear above the screen
self.history = QLabel()
zero = QPushButton("0")
# ...
This is a pyqt5 program that is suppossed to set the content of one lineedit to the content of the other lineedit. It is not working in that it you can't edit the line edits. Can someone tell me why and how I can fix it?
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
firstenter = QLineEdit(self)
firstenter.move(140,276)
firstenter.setFixedWidth(240)
secondenter = QLineEdit(self)
secondenter.move(420,276)
secondenter.setFixedWidth(240)
equalsighn = QLabel(self)
equalsighn.setText("=")
equalsighn.move(395,270)
def conversion():
try:
a = firstenter.displayText()
b = secondenter.displayText()
if firstenter.isModified() == True:
firstenter.setText(str(b))
elif secondenter.isModified() == True:
secondenter.setText(str(a))
except:
if firstenter.isModified() == True:
secondenter.setText("")
if secondenter.isModified() == True:
firstenter.setText("")
firstenter.textEdited.connect(conversion)
secondenter.textEdited.connect(conversion)
self.setGeometry(500, 300, 800, 500)
self.setWindowTitle('Test')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('Fusion')
ex = Example()
sys.exit(app.exec_())
It's not working because the logic in the first if statement is wrong:
if firstenter.isModified() == True:
firstenter.setText(str(b))
You're resetting the contents of the first line edit to the second, but since the secondenter text is empty to begin with, it sets the firstenter text accordingly, thus resetting its contents no matter what you type. Because of that, the second if won't work for the same reason.
The solution is much simpler, and uses [sender()] to know which object emitted the signal:
def conversion():
if self.sender() == firstenter:
secondenter.setText(firstenter.text())
else:
firstenter.setText(secondenter.text())
Note that you should use text() and not displayText(), since the latter might return a different result if the echoMode() is not set to Normal (the default).
Also, the try/exception is useless, and you shouldn't check against isModified, since textEdited is always and only emitted when the user changes the text, and not when the text is changed programmatically using setText().
A suggestion: avoid fixed sizes and positions, using them will probably result in an unusable interface on systems different from yours (because of various reasons, including screen size, DPI and default fonts). You should prefer layout managers instead.
My list widget placed inside a window prints out values (0 - 1000) when button1 is pressed. But some of these values are 0's and signify an error. The user is expected to update these values with any other positive integer. Once the value is confirmed by pressing a button2, the list will be updated or an error is shown that it needs to be further updated.
The following is my code.
import Ui_ImageSort # designed using Qt-Designer
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMainWindow, QListWidgetItem
class ImageSort(Ui_ImageSort.Ui_MainWindow, QMainWindow):
def __init__(self):
super(ImageSort, self).__init__()
self.setupUi(self)
self.pushButton_1.clicked.connect(list_view)
self.pushButton_2.clicked.connect(print_scales)
def list_view(self):
self.listWidget.clear()
for i in range(len(self.scale_txt)):
item = QListWidgetItem(str(self.scale_txt[i]))
self.listWidget.addItem(str(i + 1) + ") " + item.text())
def print_scales(self):
self.listWidget.clear()
error = 0
for i in range(len(self.scale_txt)):
if (self.scale_txt[i]==0):
error = 1
if (error ==0):
self.listWidget.addItem("\nThe scale values are confirmed ")
for i in range(len(self.scale_txt)):
print(self.scale_txt[i])
print("\n")
else:
self.listWidget.addItem("\nThe scale values have an error")
self.listWidget.addItem("Press button 1 again to edit")
I would like to edit only the digits the the listwidget prints out. The output will look something like this:
1) 100 microns
2) 200 microns
3) 0 microns
4) 100 microns
The value 0 needs to be corrected. So it should be marked red. And the user can change without affecting the remaining line ("microns"). For example: "0 microns" is invalid, marked in red and should be editable, but after the user replaces it with some other digits, presses button2, then it becomes valid and is, therefore, turned black and is no longer editable.
One possible solution is to use a delegate, and the data is passed through the roles:
from PyQt5 import QtCore, QtGui, QtWidgets
MaskRole = QtCore.Qt.UserRole + 1000
class ListDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
mask = index.data(MaskRole)
if mask is not None:
editor = QtWidgets.QLineEdit(parent)
editor.setInputMask(mask)
return editor
def setModelData(self, editor, model, index):
if editor.hasAcceptableInput():
text = editor.text()
model.setData(index, text, QtCore.Qt.DisplayRole)
re = QtCore.QRegularExpression(r"(\d+)\) (\d+) microns")
match = re.match(index.data())
color = QtGui.QColor("red")
if match.hasMatch():
val = match.captured(match.lastCapturedIndex())
if val != "0":
color = QtGui.QColor("black")
model.setData(index, color, QtCore.Qt.ForegroundRole)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QListWidget()
delegate = ListDelegate(w)
w.setItemDelegate(delegate)
scales = [100, 200, 0, 500, 0, 300, 0]
for i, scale in enumerate(scales):
item = QtWidgets.QListWidgetItem()
if scale == 0:
item.setData(MaskRole, "{}) 900 micro\\ns".format(i))
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
item.setForeground(QtCore.Qt.red)
item.setText("{}) {} microns".format(i, scale))
w.addItem(item)
w.show()
sys.exit(app.exec_())
I am a beginner with GUI's and PYQT. What I am trying to do is dynamically set up a grid of QComboBox's and QLineEdit's. From the QComboBox you can select a choice and from that choice, it will fill in the corresponding QLineEdit with some numbers. The problem I'm having is creating the link between the first QComboBox and the first QLineEdit box. I could make a function for each row but I would like to know a better way. I will post some sample code. Thank you for any help or advice that you might have.
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(50, 50, 700, 600)
self.home()
def home(self):
Test1Choices = ['Test1:','Choice1', 'Choice2', 'Choice3', 'Choice4','Choice5', 'Choice6', 'Choice7', 'Choice8', 'Choice9']
Test2Choices= ['Test2:','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
for i in range(0,10):
Choice1ComboBox = QComboBox(self)
Choice1ComboBox.addItems(Test1Choices)
Choice1ComboBox.resize(150,25)
Choice1ComboBox.move(30,(150+(i*35)))
Choice1ComboBox.setCurrentIndex(2)
Choice2ComboBox = QComboBox(self)
Choice2ComboBox.setObjectName("Choice2ComboBox"+str(i))
Choice2ComboBox.addItems(Test2Choices)
Choice2ComboBox.resize(75,25)
Choice2ComboBox.move(200,(150+(i*35)))
Choice2ComboBox.setCurrentIndex(2)
Choice2ComboBox.activated[str].connect(self.doSomething)
numTextBox = QLineEdit(self)
numTextBox.setObjectName("numBox"+str(i))
numTextBox.move(325,(150+(i*35)))
numTextBox.resize(35,25)
result1TextBox = QLineEdit(self)
result1TextBox.setObjectName("result1Box"+str(i))
result1TextBox.move(400,(150+(i*35)))
result1TextBox.resize(100,25)
result1TextBox.setEnabled(0)
result2TextBox = QLineEdit(self)
result2TextBox.setObjectName("result2Box"+str(i))
result2TextBox.move(525,(150+(i*35)))
result2TextBox.resize(100,25)
result2TextBox.setEnabled(0)
self.show()
def doSomething(self):
numbers=['result1','result2','result3','result4','result5','result6','result7','result8','result9','result10','result11','result12','result13','result14','result15']
def run():
app = QApplication(sys.argv)
Gui = window()
sys.exit(app.exec_())
run()
To summarize I would like to bring in the index of the selected QComboBox. Then use that index number to reference the answer that is in the "numbers" array. Then print that result in the QLineEdit that is in the same row
We use sender() to get the object that emits the signal, then we look for the name of that object with setObjectName(), and we search the index, then we get the other objects with findChildren(), for example the output will be the union of the selected texts.
add name to Choice1ComboBox:
Choice1ComboBox.setObjectName("Choice1ComboBox"+str(i))
doSomething function:
def doSomething(self, _):
sender = self.sender()
l = sender.objectName().split("Choice1ComboBox")
if len(l) > 1:
number = l[1]
else:
number = sender.objectName().split("Choice2ComboBox")[1]
combo1 = self.findChildren(QComboBox, "Choice1ComboBox"+number)[0]
combo2 = self.findChildren(QComboBox, "Choice2ComboBox"+number)[0]
obj = self.findChildren(QLineEdit, "numBox"+number)[0]
obj.setText(combo1.currentText() + " " + combo2.currentText())
Complete code:
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QMainWindow):
def __init__(self):
super(window, self).__init__()
self.setGeometry(50, 50, 700, 600)
self.home()
def home(self):
Test1Choices = ['Test1:','Choice1', 'Choice2', 'Choice3', 'Choice4','Choice5', 'Choice6', 'Choice7', 'Choice8', 'Choice9']
Test2Choices= ['Test2:','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
for i in range(0,10):
Choice1ComboBox = QComboBox(self)
Choice1ComboBox.setObjectName("Choice1ComboBox"+str(i))
Choice1ComboBox.addItems(Test1Choices)
Choice1ComboBox.resize(150,25)
Choice1ComboBox.move(30,(150+(i*35)))
Choice1ComboBox.setCurrentIndex(2)
Choice1ComboBox.activated[str].connect(self.doSomething)
Choice2ComboBox = QComboBox(self)
Choice2ComboBox.setObjectName("Choice2ComboBox"+str(i))
Choice2ComboBox.addItems(Test2Choices)
Choice2ComboBox.resize(75,25)
Choice2ComboBox.move(200,(150+(i*35)))
Choice2ComboBox.setCurrentIndex(2)
Choice2ComboBox.activated[str].connect(self.doSomething)
numTextBox = QLineEdit(self)
numTextBox.setObjectName("numBox"+str(i))
numTextBox.move(325,(150+(i*35)))
numTextBox.resize(35,25)
result1TextBox = QLineEdit(self)
result1TextBox.setObjectName("result1Box"+str(i))
result1TextBox.move(400,(150+(i*35)))
result1TextBox.resize(100,25)
result1TextBox.setEnabled(0)
result2TextBox = QLineEdit(self)
result2TextBox.setObjectName("result2Box"+str(i))
result2TextBox.move(525,(150+(i*35)))
result2TextBox.resize(100,25)
result2TextBox.setEnabled(0)
self.show()
def doSomething(self, _):
sender = self.sender()
l = sender.objectName().split("Choice1ComboBox")
if len(l) > 1:
number = l[1]
else:
number = sender.objectName().split("Choice2ComboBox")[1]
combo1 = self.findChildren(QComboBox, "Choice1ComboBox"+number)[0]
combo2 = self.findChildren(QComboBox, "Choice2ComboBox"+number)[0]
obj = self.findChildren(QLineEdit, "numBox"+number)[0]
obj.setText(combo1.currentText() + " " + combo2.currentText())
def run():
app = QApplication(sys.argv)
Gui = window()
sys.exit(app.exec_())
run()
I'm wondering if there is a way make a button send a message to a lineEdit variable in PyQt4. Here is my code so far:
import sys
from PyQt4 import QtGui,QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
qanda = QtGui.QLineEdit()
one = QtGui.QPushButton('1',self)
two = QtGui.QPushButton('2',self)
three = QtGui.QPushButton('3',self)
four = QtGui.QPushButton('4',self)
five = QtGui.QPushButton('5',self)
six = QtGui.QPushButton('6',self)
seven = QtGui.QPushButton('7',self)
eight = QtGui.QPushButton('8',self)
nine = QtGui.QPushButton('9',self)
zero = QtGui.QPushButton('0',self)
dot = QtGui.QPushButton('.',self)
minus = QtGui.QPushButton('-',self)
plus = QtGui.QPushButton('+',self)
multiply = QtGui.QPushButton('x',self)
divide = QtGui.QPushButton('/',self)
equals = QtGui.QPushButton('=',self)
backspace = QtGui.QPushButton('Backspace',self)
xsquared = QtGui.QPushButton('x^2',self)
xcubed = QtGui.QPushButton('x^3',self)
clear = QtGui.QPushButton('C',self)
one.clicked.connect(self.buttonClicked)
two.clicked.connect(self.buttonClicked)
three.clicked.connect(self.buttonClicked)
four.clicked.connect(self.buttonClicked)
five.clicked.connect(self.buttonClicked)
six.clicked.connect(self.buttonClicked)
seven.clicked.connect(self.buttonClicked)
eight.clicked.connect(self.buttonClicked)
nine.clicked.connect(self.buttonClicked)
zero.clicked.connect(self.buttonClicked)
dot.clicked.connect(self.buttonClicked)
minus.clicked.connect(self.buttonClicked)
plus.clicked.connect(self.buttonClicked)
multiply.clicked.connect(self.buttonClicked)
divide.clicked.connect(self.buttonClicked)
equals.clicked.connect(self.buttonClicked)
backspace.clicked.connect(self.buttonClicked)
xsquared.clicked.connect(self.buttonClicked)
xcubed.clicked.connect(self.buttonClicked)
clear.clicked.connect(self.buttonClicked)
grid = QtGui.QGridLayout()
grid.setSpacing(5)
grid.addWidget(qanda,0,0,1,4)
grid.addWidget(one,4,0)
grid.addWidget(two,4,1)
grid.addWidget(three,4,2)
grid.addWidget(four,3,0)
grid.addWidget(five,3,1)
grid.addWidget(six,3,2)
grid.addWidget(seven,2,0)
grid.addWidget(eight,2,1)
grid.addWidget(nine,2,2)
grid.addWidget(zero,5,0)
grid.addWidget(dot,5,1)
grid.addWidget(minus,5,3)
grid.addWidget(plus,4,3)
grid.addWidget(multiply,2,3)
grid.addWidget(divide,3,3)
grid.addWidget(equals,5,2)
grid.addWidget(backspace,1,0)
grid.addWidget(xsquared,1,1)
grid.addWidget(xcubed,1,2)
grid.addWidget(clear,1,3)
self.setLayout(grid)
self.setGeometry(300, 300, 250, 200)
self.setWindowTitle('ldm;sasdklhsdghk dgh jkl;')
self.show()
def buttonClicked(self):
sender = self.sender()
print(sender.text())
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
My goal is when someone clicks a button, such as x^2, x^2 will be displayed on the empty space that is the variable qanda.
If you are wondering, this is a calculator.
You need to keep a reference to the line-edit so that you can access it later:
def initUI(self):
self.qanda = QtGui.QLineEdit(self)
...
grid.addWidget(self.qanda,0,0,1,4)
...
Now you can set the text of the line-edit, like so:
def buttonClicked(self):
sender = self.sender()
print(sender.text())
self.qanda.setText(sender.text())
Have you tried setText method?
http://pyqt.sourceforge.net/Docs/PyQt4/qlineedit.html#setText