I'm extremely new to Pygtk and Stackoverflow in general. I'm trying to build a small dictionary application: I have one master VBox and an Hbox containing two Vboxes divided by a Vseparator. I am trying to display text through a label in the right-hand Vbox, but it will not appear. Here's my pitiful code:
import gtk
import pygtk
from Wordlist import *
pygtk.require('2.0')
def click_handler(button):
for i in nouns:
print i
k = gtk.Label(str=i)
k.show()
meaningvbox.pack_start(k,True,True,0)
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(300,400)
window.set_title("English-Japanese Reference")
window.show()
window.connect("delete-event", gtk.main_quit)
vbox = gtk.VBox(False,0)
window.add(vbox)
vbox.show()
hbox = gtk.HBox(True,0)
vbox.pack_end(hbox,False)
hbox.show()
hbox2 = gtk.HBox(True,0)
vbox.pack_end(hbox2,False)
hbox2.show()
vsep = gtk.VSeparator()
vbox.pack_start(vsep)
vsep.show()
dichbox = gtk.HBox() #### These are boxes created to store the words
vbox.pack_start(dichbox)
wordvbox = gtk.VBox()
dichbox.pack_start(wordvbox)
wordvbox.show()
meaningvbox = gtk.VBox()
dichbox.pack_start(meaningvbox)
meaningvbox.show()
label = gtk.Label(str="hi")
meaningvbox.pack_start(label)
label.show()
verbButton = gtk.Button(label="Verbs")
hbox.pack_end(verbButton,True,False)
verbButton.set_size_request(100,30)
verbButton.show()
nounButton = gtk.Button(label="Nouns")
nounButton.set_size_request(100,30)
hbox.pack_end(nounButton,True,False)
nounButton.show()
nounButton.connect("clicked", click_handler)
familyButton = gtk.Button(label="Family")
familyButton.set_size_request(100,30)
hbox.pack_end(familyButton,True,False)
familyButton.show()
particleButton = gtk.Button(label="Particles")
hbox2.pack_end(particleButton,True,False)
particleButton.set_size_request(100,30)
particleButton.show()
adjectiveButton = gtk.Button(label="Adjectives")
adjectiveButton.set_size_request(100,30)
hbox2.pack_end(adjectiveButton,True,False)
adjectiveButton.show()
pronounButton = gtk.Button(label="Pronouns")
pronounButton.set_size_request(100,30)
hbox2.pack_end(pronounButton,True,False)
pronounButton.show()
def main():
gtk.mainloop()
main()
You forgot to call dichbox.show().
I would also recommend to restructure your code and group similar function calls, use show_all() instead of many show()s and use a class for the whole window.
That's what it would look like:
import pygtk
pygtk.require('2.0')
import gtk
from Wordlist import *
class Window(gtk.Window):
def __init__(self):
gtk.Window.__init__(self,gtk.WINDOW_TOPLEVEL)
self.set_size_request(300,400)
self.set_title("English-Japanese Reference")
self.connect("delete-event", gtk.main_quit)
verbButton = gtk.Button(label="Verbs")
nounButton = gtk.Button(label="Nouns")
nounButton.connect("clicked", self.click_handler)
familyButton = gtk.Button(label="Family")
particleButton = gtk.Button(label="Particles")
adjectiveButton = gtk.Button(label="Adjectives")
pronounButton = gtk.Button(label="Pronouns")
verbButton.set_size_request(100,30)
nounButton.set_size_request(100,30)
familyButton.set_size_request(100,30)
particleButton.set_size_request(100,30)
adjectiveButton.set_size_request(100,30)
pronounButton.set_size_request(100,30)
hbox = gtk.HBox(True,0)
hbox.pack_end(verbButton, True, False)
hbox.pack_end(nounButton, True, False)
hbox.pack_end(familyButton, True, False)
hbox2 = gtk.HBox(True,0)
hbox2.pack_end(particleButton, True, False)
hbox2.pack_end(adjectiveButton, True, False)
hbox2.pack_end(pronounButton, True, False)
label = gtk.Label("hi")
self.meaningvbox = gtk.VBox()
self.meaningvbox.pack_start(label)
wordvbox = gtk.VBox()
vsep = gtk.VSeparator()
dichbox = gtk.HBox()
dichbox.pack_start(wordvbox)
dichbox.pack_start(vsep)
dichbox.pack_start(self.meaningvbox)
vbox = gtk.VBox(False, 0)
vbox.pack_end(hbox, False)
vbox.pack_end(hbox2, False)
vbox.pack_start(dichbox)
self.add(vbox)
self.show_all()
def click_handler(self,button):
for i in nouns:
k = gtk.Label(i)
k.show()
self.meaningvbox.pack_start(k, True, True, 0)
def main():
win = Window()
gtk.main()
main()
Related
Button(
onClick = {
raceOn = !raceOn
if (raceOn) {
text.value = "Stop!"
color.value = Color.Red
} else {
text.value = "Go!"
color.value = Color.Green
}
},
modifier = Modifier.background(color = color.value),
content = {
Text(
text = "${text.value}",
)
}
)
Using the code above, I got the attached image. What I want is the inside of the button to be green and not the background behind it. I couldn't the right property to modify.
Has anyone here tried to modify the Button background? Or perhaps suggest another solution. I tried the OutlinedButton and wasn't successful.
Thanks!
Use the MaterialTheme ButtonColors.
val colors: ButtonColors = ButtonDefaults.primaryButtonColors(backgroundColor = Color.Red)
Button(onClick = { /*TODO*/ }, colors = ButtonDefaults.primaryButtonColors()) {
// TODO
}
You can also update via setting the MaterialTheme defaults.
val wearColorPalette: Colors = Colors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200,
secondaryVariant = Teal200,
error = Red400,
onPrimary = Color.Black,
onSecondary = Color.Black,
onError = Color.Black
)
...
MaterialTheme(
colors = wearColorPalette,
typography = Typography,
// For shapes, we generally recommend using the default Material Wear shapes which are
// optimized for round and non-round devices.
content = content
)
Is there a function or option that adds an image in PushButton widget? In this situation, The added image means an image as a background applied to the entire widget, not an image as an 'icon'. I tried to find this option and I use the 'setStyleSheet' function, but it doesn't work. What is a problem, and how can I add an image in pushbutton?
btn6.setStyleSheet(
"color: black;"
"border-style: solid;"
"border-width: 2px;"
"border-color: #FFB400;"
"border-radius: 3px;"
"background-color: #FFD732;"
"**background-image: url('D:\PyQt5_Tutorial\Test.png')")**
You can just override QPushButton.paintEvent() for this. And dont forget to add interactivity to reflect different states of button: sunken, disabled, mouse hover, input focus.
from PyQt5 import QtWidgets, QtGui
class Button(QtWidgets.QPushButton):
def __init__(self, parent = None) -> None:
super().__init__(parent)
self._image = None
def setImage(self, image):
self._image = image
self.update()
class Button(QtWidgets.QPushButton):
def __init__(self, parent = None) -> None:
super().__init__(parent)
self._image = None
def setImage(self, image):
self._image = image
self.update()
def paintEvent(self, event):
if self._image is None:
return
opt = QtWidgets.QStyleOptionButton()
self.initStyleOption(opt)
rect = self.rect()
painter = QtGui.QPainter(self)
self.style().drawControl(QtWidgets.QStyle.CE_PushButtonBevel, opt, painter, self)
if opt.state & QtWidgets.QStyle.State_Sunken:
rect.adjust(2,2,2,2)
painter.drawImage(rect, self._image)
if opt.state & QtWidgets.QStyle.State_MouseOver:
color = self.palette().color(QtGui.QPalette.Highlight)
color.setAlpha(50)
painter.fillRect(self.rect(), color)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
button = Button()
button.setImage(QtGui.QImage("D:\\PyQt5_Tutorial\\Test.png"))
button.show()
app.exec()
The docking is created as required. What I'm not able to do is creating 'Shelf' widget above docking.
It shouldn't be part of docking and it should remain at the top. When hidden, docks should cover up the
space and when shown again docks should move below.
import sys
from PySide2 import QtGui, QtCore, QtWidgets
class Shelf(QtWidgets.QTabWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tab1 = QtWidgets.QWidget()
self.tab2 = QtWidgets.QWidget()
self.tab3 = QtWidgets.QWidget()
self.addTab(self.tab1, "Tab 1")
self.addTab(self.tab2, "Tab 2")
self.addTab(self.tab3, "Tab 3")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.centre = QtWidgets.QMainWindow(self)
self.centre.setWindowFlags(QtCore.Qt.Widget)
self.centre.setDockOptions(
QtWidgets.QMainWindow.AnimatedDocks |
QtWidgets.QMainWindow.AllowNestedDocks)
self.setCentralWidget(self.centre)
self.dockCentre1 = QtWidgets.QDockWidget(self.centre)
self.dockCentre1.setWindowTitle('Centre 1')
self.centre.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockCentre1)
self.dockCentre2 = QtWidgets.QDockWidget(self.centre)
self.dockCentre2.setWindowTitle('Centre 2')
self.centre.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockCentre2)
self.dockLeft = QtWidgets.QDockWidget(self)
self.dockLeft.setWindowTitle('Left')
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockLeft)
self.dockLeft1 = QtWidgets.QDockWidget(self)
self.dockLeft1.setWindowTitle('Left')
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dockLeft1)
self.dockRight = QtWidgets.QDockWidget(self)
self.dockRight.setWindowTitle('Right')
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockRight)
self.dockRight1 = QtWidgets.QDockWidget(self)
self.dockRight1.setWindowTitle('Right')
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockRight1)
self.menuBar().addMenu('File').addAction('Quit', self.close)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.setGeometry(500, 50, 600, 400)
window.show()
sys.exit(app.exec_())
I try to connect a QtGui.QPlainTextEdit to a Model with QDataWidgetMapper.
I dont get any errors, just nothing in the TextEdit.
I dont get it and i cant find good example Code.
Here is some ExampleCode.
I really hope that someone could help me.
from PySide import QtCore, QtGui
import sys
class ComponentsListModel(QtCore.QAbstractListModel):
def __init__(self, components=[], parent = None):
super(ComponentsListModel, self).__init__(parent=None)
self.components = components
self.list = parent
def rowCount(self, parent):
return len(self.components)
def data(self, index, role):
row = index.row()
if role == QtCore.Qt.DisplayRole:#index.isValid() and
value = self.components[row]
return value
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self._build_ui()
def _build_ui(self):
self.layout = QtGui.QVBoxLayout()
self.listView = QtGui.QListView()
self.model = ComponentsListModel(components = ['1', '2', '3'])
self.listView.setModel(self.model)
self.text = QtGui.QPlainTextEdit()
self.layout.addWidget(self.listView)
self.layout.addWidget(self.text)
self.setLayout(self.layout)
self._mapper = QtGui.QDataWidgetMapper(self)
self._mapper.setModel(self.model)
self._mapper.setSubmitPolicy(QtGui.QDataWidgetMapper.AutoSubmit)
self._mapper.addMapping(self.text, 0)
self._mapper.toFirst()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
app.setStyle('Plastique')
mySW = MainWindow()
mySW.show()
sys.exit(app.exec_())
You will need to add a condition for Qt.EditRole in your data function inside ComponentsListModel class
if role == Qt.EditRole:
value = self.components[row]
return value
Is there a succinct example of how to upload an image, resize it, store it in a database and then serve the image up using Lift?
I'm sure I could piece it together from the file upload, Java 2D API, Lift Mapper and Response APIs. But is there any example code I can follow to do it the 'correct' or recommended way?
I did this for a Mapper field linked to s3 by creating a new MappedField. I also have a some code to resize, but haven't tested or deployed (so use with caution).
class MappedS3Image[T<:Mapper[T]](owner: T, val path:String, maxWidth: String, maxHeight:String) extends MappedString[T](owner, 36) {
def url:String = MappedS3Image.fullImgPath(path, is)
def setFromUpload(fileHolder: Box[FileParamHolder]) = {
S3Sender.uploadImageToS3(path, fileHolder).map(this.set(_))
}
override def asHtml:Node = <img src={url} style={"max-width:" + maxWidth + ";max-height:"+maxHeight} />
override def _toForm: Box[Elem] = Full(SHtml.fileUpload(fu=>setFromUpload(Full(fu))))
}
import java.awt.Image
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
import java.awt.Graphics2D
import java.awt.AlphaComposite
object ImageResizer {
def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = {
val originalImage:BufferedImage = ImageIO.read(is)
val height = originalImage.getHeight
val width = originalImage.getWidth
if (width <= maxWidth && height <= maxHeight)
originalImage
else {
var scaledWidth:Int = width
var scaledHeight:Int = height
val ratio:Double = width/height
if (scaledWidth > maxWidth){
scaledWidth = maxWidth
scaledHeight = (scaledWidth.doubleValue/ratio).intValue
}
if (scaledHeight > maxHeight){
scaledHeight = maxHeight
scaledWidth = (scaledHeight.doubleValue*ratio).intValue
}
val scaledBI = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB)
val g = scaledBI.createGraphics
g.setComposite(AlphaComposite.Src)
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose
scaledBI
}
}
}
The other answer nicely describes how to resize the image and store a reference to the file on the file system.
If you want to use the lift mapper to store the actual file contents, you have to create your custom model object, and define a binary field on it. Try something like this:
package code {
package model {
import _root_.net.liftweb.mapper._
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._
// singleton object which manipulates storing of Document instances
object Document extends Document with KeyedMetaMapper[Long, Document] {
}
class Document extends KeyedMapper[Long, Document] {
def getSingleton = Document
def primaryKeyField = id
object id extends MappedLongIndex(this)
object name extends MappedString(this, 20) {
override def displayName = "Name"
override def writePermission_? = true
}
object content extends MappedBinary(this) {
override def displayName = "Content"
override def writePermission_? = true
}
}
}
}
Then, in bootstrap class, add this Document at the end:
Schemifier.schemify(true, Schemifier.infoF _, User, Document)
Voila. Using Document save (new Document) stores it into database. A new Document's fields can be set using the set method. Try playing with delete_!, find, findAll methods of the Document singleton to delete or find it in the database. It should be straightforward from this point on.
Finally, to display the image, you can override Lift's dispatching rules (in bootstrap class, Boot.scala). Try playing around with this example which overrides the rules for pdf requests:
def getFile(filename: String): Option[Document] = {
val alldocs = Document.findAll()
alldocs.find(_.name.get == filename)
}
LiftRules.statelessDispatchTable.append {
case Req("file" :: name :: Nil, "pdf", GetRequest) =>
() =>
println("Got request for: " + name + ".pdf")
for {
stream <- tryo(
getFile(name + ".pdf") map {
doc => new java.io.ByteArrayInputStream(doc.content.get)
} getOrElse null
)
if null ne stream
} yield StreamingResponse(stream,
() => stream.close,
stream.available,
List("Content-Type" -> "application/pdf"),
Nil,
200)
}
Based on the accepted answer by Jon Hoffman, I fixed the bugs. His version messes up the aspect ratio (it always becomes 1:1), because the math was off in a few spots. This version resizes big pictures until they fit, and respects the aspect ratio.
def resize(is:java.io.InputStream, maxWidth:Int, maxHeight:Int):BufferedImage = {
require (maxWidth > 0)
require (maxHeight > 0)
val originalImage:BufferedImage = ImageIO.read(is)
var height = originalImage.getHeight
var width = originalImage.getWidth
// Shortcut to save a pointless reprocessing in case the image is small enough already
if (width <= maxWidth && height <= maxHeight)
originalImage
else {
// If the picture was too big, it will either fit by width or height.
// This essentially resizes the dimensions twice, until it fits
if (width > maxWidth){
height = (height.doubleValue() * (maxWidth.doubleValue() / width.doubleValue())).intValue
width = maxWidth
}
if (height > maxHeight){
width = (width.doubleValue() * (maxHeight.doubleValue() / height.doubleValue())).intValue
height = maxHeight
}
val scaledBI = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
val g = scaledBI.createGraphics
g.setComposite(AlphaComposite.Src)
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose
scaledBI
}
}