GTK changing background image of window - image

how can I achieve it? I was searching for it for like 30 minutes and found examples which don't work or work in bad way. I simply want to change background image of window without changing bakgrounds of other dialogs windows etc? But I want buttons and labels to be transparent on that background.

I found a python example that worked for me at:
http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html
Code
#!/usr/bin/env python
import gtk
def draw_pixbuf(widget, event):
path = '/home/markuz/wallpapers/WMwall1024x768.gif'
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
widget.window.draw_pixbuf(widget.style.bg_gc[gtk.STATE_NORMAL], pixbuf, 0, 0, 0,0)
window = gtk.Window()
window.set_title('Drawing Test')
window.set_size_request(640,480)
window.connect('destroy',gtk.main_quit)
hbbox = gtk.HButtonBox()
window.add(hbbox)
hbbox.connect('expose-event', draw_pixbuf)
button = gtk.Button('Press Me!')
hbbox.pack_start(button, True, False, 10)
window.show_all()
gtk.main()
I also found a C example at:
http://www.gtkforums.com/viewtopic.php?t=446
Code
GtkWidget *SetupWindow(gchar *data,gboolean Transient)
{
GdkPixmap *background;
GdkPixbuf *pixbuf;
GdkScreen *ourscreen;
GdkColormap *colormap;
GtkStyle *style;
GdkColor fg;
GdkColor bg;
GError *error = NULL;
GdkRectangle *rect;
GtkWidget *window;
pixbuf = gdk_pixbuf_new_from_file ("pics/fb.png",&error);
if (error != NULL) {
if (error->domain == GDK_PIXBUF_ERROR) {
g_print ("Pixbuf Related Error:\n");
}
if (error->domain == G_FILE_ERROR) {
g_print ("File Error: Check file permissions and state:\n");
}
g_printerr ("%s\n", error[0].message);
exit(1);
}
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &background, NULL, 0);
style = gtk_style_new ();
style->bg_pixmap[0] = background;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), data);
// gtk_window_maximize(GTK_WINDOW(window));
gtk_window_set_modal (GTK_WINDOW (window),TRUE);
gtk_window_set_default_size(GTK_WINDOW(window),640,480);
gtk_widget_set_style (GTK_WIDGET(window), GTK_STYLE(style));
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER_ALWAYS);
gtk_container_set_border_width(GTK_CONTAINER(window), 14);
if(Transient==TRUE)
gtk_window_set_transient_for(GTK_WINDOW (window),GTK_WINDOW(mainwindow));
gtk_widget_show (window);
return(window);
}
But I didn't try it.

It works!
import re,os, time, socket, datetime, threading, subprocess, fileinput, gobject, gst, gtk, logging
logging.basicConfig(filename='/var/tmp/log.log',level=logging.DEBUG)
gobject.threads_init()
def thread1(s):
logging.debug("uploading")
os.system("""/var/tmp/upload.download.largest.sh %s %s &""" % (s[1], s[2]) )
class server(object):
def __init__(self):
button_rc = """
pixmap_path "/var/tmp"
# 1) Background > Image > change the logo.png
style "window" {
bg_pixmap[NORMAL] = "logo.png"
}
# imports
widget_class "GtkWindow" style "window"
"""
""" Window """
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(6400, 6400, 6440))
self.window.set_size_request(1280, 720)
self.window.set_border_width(1)
self.window.set_decorated(False)
self.window.set_title("server")
self.window.move(0,0)
self.window.set_name("main window")
gtk.rc_parse_string(button_rc) # 2) important line for the background image
self.window.connect("delete-event", gtk.main_quit)
self.window.connect ('button-press-event',self.callback)
self.window.set_events(gtk.gdk.EXPOSURE_MASK | gtk.gdk.LEAVE_NOTIFY_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK| gtk.gdk.POINTER_MOTION_HINT_MASK )
self.window.show_all()
self.window.set_keep_above(True)
if(self.window.get_window().get_state() == gtk.gdk.WINDOW_STATE_MAXIMIZED):
self.window.unmaximize()
def callback(self):
logging.debug("uploading")
def quit(self, window):
gtk.main_quit()
def run(self):
gtk.main()
if __name__=='__main__':
t = server()
t.run()

Related

PyQt5 - How can I add image in 'pushbutton' widget? | (not icon)

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()

Cannot Get Pygtk to Display Label in Hbox

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()

Add custom action to System Menu in a QDialog

I have a need to add a custom action (say ‘About’ clicking which a QMessageBox needs to be displayed) in the system menu shown when the icon on the title bar of a QDialog is clicked. How do I achieve this?
Regards,
Bharath
You cannot do it with Qt because it's OS specific. But you can use GetSystemMenu and AppendMenu functions in Windows to modify the menu and then catch events that then item is clicked.
Here is a simple example from here. It appends a separator and an about item to the menu:
#include "windows.h"
// IDM_ABOUTBOX must be in the system command range
// (IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX)
// and (IDM_ABOUTBOX < 0xF000)
#define IDM_ABOUTBOX 0x0010
MyWidget::MyWidget() : QMainWindow()
{
...
HMENU hMenu = ::GetSystemMenu(winId(), FALSE);
if (hMenu != NULL)
{
::AppendMenuA(hMenu, MF_SEPARATOR, 0, 0);
::AppendMenuA(hMenu, MF_STRING, IDM_ABOUTBOX, "About MyApp...");
}
...
}
bool MyWidget::winEvent(MSG *m, long *result)
{
if (m->message == WM_SYSCOMMAND)
{
if ((m->wParam & 0xfff0) == IDM_ABOUTBOX)
{
*result = 0;
// open About dialog
about();
return (true);
}
}
return (false);
}
PRO-file:
LIBS += -lUser32

Is possible to put an image instead of a button, and make it clickable?

Is possible to put an Image into a GUI Application and make it clickable?
I used to make a button like this:
img = QPixmap(15, 15)
img.fill(Qt.grey)
button = QPushButton(QIcon(img))
button.clicked.connect(self.button_click)
Link http://imagizer.imageshack.us/v2/800x600q90/834/kaqc.png
But I'd prefer to use an image, instead of having a button with an icon..
I had the same requirement and solved it by subclassing QLabel, as yshurik suggests. The amount of additional code is very limited. Here is a working implementation:
class CClickableLabel : public QLabel
{
Q_OBJECT
public:
CClickableLabel(QString text, QWidget *parent = 0) : QLabel(text, parent) {}
~CClickableLabel() {}
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent *event) { emit clicked(); }
};
Create a instance CClickableLabel, use setPixmap() to set the image and listen to the clicked() signal. That should do the trick.
Here's simple demo script that shows how to make a grid of clickable labels:
from random import shuffle
from PySide import QtCore, QtGui
class ClickableLabel(QtGui.QLabel):
clicked = QtCore.Signal(str)
def __init__(self, width, height, color):
super(ClickableLabel, self).__init__()
pixmap = QtGui.QPixmap(width, height)
pixmap.fill(QtGui.QColor(color))
self.setPixmap(pixmap)
self.setObjectName(color)
def mousePressEvent(self, event):
self.clicked.emit(self.objectName())
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QGridLayout(self)
colors = 'red green blue orange purple yellow'.split()
for row in range(len(colors)):
shuffle(colors)
for column, color in enumerate(colors):
label = ClickableLabel(25, 25, color)
label.clicked.connect(self.handleLabelClicked)
layout.addWidget(label, row, column)
def handleLabelClicked(self, name):
print('"%s" clicked' % name)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 200, 200)
window.show()
sys.exit(app.exec_())
I guess the fast solution is subclass QLabel, use setPixmap() to put image on and reimplement mouseEvent() to submit signal clicked() on press/release event. As it is python (PyQt/PySide) then it should be just few lines. Usually I use such approach when need some graphics clickable.
Buttons are style able, and you can put images on them.

How do I use an image as the background of a gtk toolbar in GTK+2.0

Is there any api like gtk_widget_modify_bg() to modify the background of a gtk toolbar by an image.
gtk_widget_modify_bg() only can change the color of the background.
After one day's try, now I has known how to set an image backgroud for a gtk toolbar.
The keypoint is that you could not directly modify background for GtkToolbar or even GtkVBox (generally you would put GtkToolbar in a GtkVBox). Because they are all none window GtkWidget, so they couldn't catch expose-event, then can't draw their own background. Their background are same as their parent.
But the GtkEventBox can. So you can put the GtkToolbar into a GtkEventBox, and put GtkEventBox into a GtkVBox. Then you modify GtkEventBox's backgroud by an image, It seems GtkToolBar's background changed.
Following is my test codes:
int main(int argc, char* argv[])
{
GtkWidget* window;
GtkWidget* vbox;
GtkWidget* event_box;
GtkWidget* toolbar;
GtkToolItem* item;
gtk_init(&argc, &argv);
gtk_rc_parse("./gtk.rc");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 250, 200);
gtk_window_set_title(GTK_WINDOW(window), "toolbar");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
event_box = gtk_event_box_new();
//gtk_widget_set_name(vbox, "toolbar_event_box");
//set_event_box_background(event_box);
gtk_box_pack_start(GTK_BOX(vbox), event_box, FALSE, FALSE, 5);
toolbar = gtk_toolbar_new();
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
item = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_separator_tool_item_new();
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
item = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(gtk_main_quit), NULL);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
gtk_container_add(GTK_CONTAINER(event_box), toolbar);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
and I use gtkrc file to set the GtkEventBox backgroud. Following is the gtk.rc:
pixmap_path "/usr/share/pixmaps:/usr/share/myself"
style "window"
{
bg_pixmap[NORMAL] = "firefox.png"
}
style "toolbar"
{
bg_pixmap[NORMAL] = "bk.bmp"
}
widget_class "GtkWindow" style "window"
widget_class "GtkEventBox" style "toolbar"
The result of the program run:
If you don't use gtkrc file, you can use gtk_widget_set_style() to change the GtkEventBox background. like this:
void set_event_box_background(GtkWidget* event_box)
{
GError* error = NULL;
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file("/usr/share/myself/bk.bmp", &error);
GdkPixmap *pixmap = NULL;
GdkPixmap *mask = NULL;
gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask, 255);
GtkStyle* orig_style = gtk_widget_get_style(event_box);
GtkStyle* style = gtk_style_copy(orig_style);
style->bg_pixmap[GTK_STATE_NORMAL] = pixmap;
gtk_widget_set_style(event_box, style);
}
I get this method from Yuren's Info Area.
When you use this method, you should comment gtk_rc_parse("./gtk.rc"); and uncomment set_event_box_background(event_box); line at above main() function.

Resources