gtk3 flowbox child 4px padding - python-2.7

I am trying to find a way to get rid of the padding around GtkFlowBox children in PyGtk3.
Here is a minimal example which exhibits the 4px padding around each child.
#!/usr/bin/python2.7
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
window = Gtk.Window()
flowbox = Gtk.FlowBox()
label0 = Gtk.Label("Test0")
label1 = Gtk.Label("Test1")
flowbox.add(label0)
flowbox.add(label1)
window.add(flowbox)
window.show_all()
window.connect('delete-event', lambda window, event: Gtk.main_quit())
print label0.get_allocated_height()
print flowbox.get_child_at_index(0).get_allocated_height()
Gtk.main()
Padding with flowbox;
http://forgottendream.org/~chasm/with_flowbox.png
Desired result without padding. (Default behavior with a GtkBox);
http://forgottendream.org/~chasm/with_box.png
Python version: 2.7.7
Gtk version: 3.12.2
EDIT: The following got rid of the extra space resulting in the same appearance as a GtkBox.
style_provider = Gtk.CssProvider()
style_provider.load_from_data("""
GtkFlowBoxChild {
padding: 0px;
}
GtkFlowBoxChild GtkLabel {
padding: 0px;
}
""");
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);

usually a padding of a widget is depends on Gtk.StyleContext () which is your gtk-theme. By default widget has allocated padding arounds it. Play with Gtk.StyleContext to get-set the padding. Or play with "margin"s property of Gtk.Widget. Personally this Gtk.FlowBox are utterly crap unless you want to filter-sort its children, who sorted and filter widgets?

Related

Adjusting the font size and family of extra fillText labels in ChartJS

I have created a pretty good ChartJS system but am having trouble with breaking the extra x-axis labels and title font details. They same to want to be the same for some reason.
First of all, the solution I got help with is here:
SO answer
The charts look okay like so:
As you can see the title and addition x-axis label are both the same font size. This occurs due to the configuration options of:
// context.xAxes.font
context.font = this.config.get("chart.axis.font");
context.fontSize = 100;
context.fillStyle = this.config.get("chart.axis.font.color");
context.textAlign = 'center';
context.fillText(line, x, y);
I have the configuration options setup this way:
title: {
display: true,
fontSize: 10,
text: this.options.title,
padding: titlePadding,
},
I have no idea why the fillText is working for both title and extra categories.
As far as I know, there's no fontSize property on the canvas rendering context. You should use its font property instead to specify weight, size, and family of the font.
Please take a look at the runnable code snippet provided in this answer.

PyQt5 QComboBox list items changing postion

I am facing some issue with the display style of Qcombobox items. Currently am hardcoding the data to be shown in the combobox.
here is the code :
self.Dummy = QComboBox(self)
self.Dummy.setGeometry(200,600, 350, 50)
self.Dummy.setStyleSheet("QComboBox {background-color: white;border-style: outset;" border-width: 2px;border-radius: 5px;border-color: #448aff; font: 12px; min-width: 10em; padding: 3px;}")
self.Dummy.addItems(["-Select-", "2", "3","4","5","6","7","8","9","0","11",])
The issue is that the dropdown "list" postion keeps changing after each selection. Here is the image of the issue am facing.
Below is my combobox
The list contains items <-Select->,2,3,4,5,6,7,8,9,0,11 , where <-Select-> will be the first element shown.
Now when I click the box, the box list "down" the elements and suppose I selected '2'. Then, if I try to select another item, the list will be dropped in a "downwards" direction. see below
Now, say if selected the last element from the items, '11'. Now if I try to select a new item by clicking on the box, the list will be popped "up" instead of down. see below
What should be done to fix it ? I don't think its an issue with stylesheet, without it also, this issue is happening. The reason I need this to be fixed is that when the list is popping up, its covering the label above it
What you see is a behavior that is OS and style dependent.
To avoid it, the best way is to subclass QComboBox and overwrite showPopup(), then we call the base class implementation (which is responsible of showing, resizing and positioning the popup view) and move it if necessary.
class Combo(QtWidgets.QComboBox):
def showPopup(self):
super().showPopup()
# find the widget that contains the list; note that this is *not* the view
# that QComboBox.view() returns, but what is used to show it.
popup = self.view().window()
rect = popup.geometry()
if not rect.contains(self.mapToGlobal(self.rect().center())):
# the popup is not over the combo, there's no need to move it
return
# move the popup at the bottom left of the combo
rect.moveTopLeft(self.mapToGlobal(self.rect().bottomLeft()))
# ensure that the popup is always inside the edges of the screen
# we use the center of the popup as a reference, since with multiple
# screens the combo might be between two screens, but that position
# could also be completely outside the screen, so the cursor position
# is used as a fallback to decide on what screen we'll show it
done = False
for i, pos in enumerate((rect.center(), QtGui.QCursor.pos())):
for screen in QtWidgets.QApplication.screens():
if pos in screen.geometry():
screen = screen.geometry()
if rect.x() < screen.x():
rect.moveLeft(screen.x())
elif rect.right() > screen.right():
rect.moveRight(screen.right())
if rect.y() < screen.y():
rect.moveTop(screen.y())
elif rect.bottom() > screen.bottom():
# if the popup goes below the screen, move its bottom
# *over* the combo, so that the its current selected
# item will always be visible
rect.moveBottom(self.mapToGlobal(QtCore.QPoint()).y())
done = True
break
if done:
break
popup.move(rect.topLeft())
This can also be done without subclassing (for example if you have many combos, you created the UI from Designer and don't want to use promoted widgets), but you'll have to remember to change all referencies to the combo.
class MyWindow(QtWidgets.QWidget):
def __init__(self):
# ...
self.combo = QtWidgets.QComboBox()
self.combo.showPopup = self.showPopupAndCheck
def showPopupAndCheck(self):
QtWidgets.QComboBox.showPopup(self.combo)
popup = self.view().window()
rect = popup.geometry()
if not rect.contains(self.combo.mapToGlobal(self.combo.rect().center())):
# the popup is not over the combo, there's no need to move it
return
# change everything from self to self.combo
Alternatively, if you want to keep this behavior consistent through all your program without always using the subclass, you can use some sort of monkey patching hack.
The advantage is that any QComboBox you create (even when loading UI files or creating a combo at runtime) will always use the new behavior.
Important: this MUST be at the very beginning of the main file of your program, possibly just after the import section.
from PyQt5 import QtCore, QtGui, QtWidgets
def customShowPopup(self):
# we can't use super(), because we're not in the class definition, but
# calling the class method with "self" as first argument is practically the
# same thing; note the underscore!
QtWidgets.QComboBox._showPopup(self)
popup = self.view().window()
# ... go on, exactly as above
# create a new reference to the showPopup method, which is the one we've used
# in the function above
QtWidgets.QComboBox._showPopup = QtWidgets.QComboBox.showPopup
# overwrite the original reference with the new function
QtWidgets.QComboBox.showPopup = customShowPopup

Qt/QML: Text with inline QML elements

We are building a graphical user interface with QtQuick/QML. We have some dynamic, multi-line text coming from a database, which should be displayed in the application. Currently, we are using the Text element to display the text. However, we need some QML components inline embedded into the text. For this, the text coming from the database contains placeholders such as ::checkbox|1:: which should then be replaced and displayed by the program.
In HTML, this is easy, you can simply mix inline elements with text to produce a result like this:
but in QML, this seems to be more difficult, as Text elements cannot be word-wrapped into two halves if there is not enough space (both the text and the container size should be dynamic).
The best solution we could come up with, is creating a Flow layout with one Text element for each word, but this seems too hacky.
Using RichText with HTML is not enogh, since we really need our custom QML elements in the text.
Also, we want to avoid using a WebView due to performance reasons.
Is there a sophisticated way to implement this with QML/C++ only?
You can create custom widgets and embed them into QML:
Writing QML Extensions with C++
I haven't tried placing something in the middle, but I did try adding a tag to the beginning (and I might try adding a tag at the end).
QML's Text has a lineLaidOut signal that let's you indent the first line of text.
http://doc.qt.io/qt-5/qml-qtquick-text.html#lineLaidOut-signal
Here's what I did:
Text {
text: issue.summary
onLineLaidOut: {
if (line.number == 0) {
var indent = tagRect.width + tagRect.rightMargin
line.x += indent
line.width -= indent
}
}
Rectangle {
id: tagRect
implicitWidth: padding + tagText.implicitWidth + padding
implicitHeight: padding + tagText.implicitHeight + padding
color: "#400"
property int padding: 2
property int rightMargin: 8
radius: 3
Text {
id: tagText
anchors.centerIn: parent
text: issue.product
color: "#fff"
}
}
}

Kivy: Make class A's method affect class B's object's property?

I have been working with Kivy for the past 3 weeks to build a GUI for a radio simulator with two radios, each with a 16-button keypad, multi-position knob, and data display.
How do I refer to objects in my .kv file to act on them with methods declared by a different object in the .py file? I can use self to make an object do things to itself, but I cannot figure out how to make one object's method influence another object.
In the .kv below, I can use on_press() to make a button change the text property of another object. However, I am too indented to add a conditional action, such as: if knob8.index == 0, then radio_output.text = radio_output.text + '0'. Apparently I must use my own methods, but I don't understand how to reference or affect other objects through them.
A ScreenManager object is my root and contains 3 Screen objects. ScreenTwo is where I am working now. I want to be able to use the change_image() method of Knob_8_Pos to change the value of any property of the Button in the .kv file below. Being able to do so would open the door to much more functionality, because the knob's position determines what the multiple buttons can do and when.
I have tried to use ids[] in the method but failed. I had hoped to use something like parent to refer to an object one level higher in the hierarchy from the object calling the function, but that was not an option.
<ScreenTwo>:
FloatLayout:
id: screentwo_layout
DisplayLabel:
id: radio_output
text: 'Buttons and stuff change this field'
Button:
id: button_0
text: "but_0"
size_hint: 0.06,0.1
pos_hint: {'center_x':0.2, 'center_y':0.47}
on_press:
radio_output.text = radio_output.text + '0'
print(radio_output.text)
background_normal: 'Images/normal.png'
background_down: 'Images/down.png'
border: 20,20,20,20
Knob_8_Pos:
id: knob8
size_hint: 0.19,0.35
pos_hint: {'center_x':0.725, 'center_y':0.38}
on_press:
self.change_image(self)
The method change_image() is in my main.py file, some of which follows. I have been playing with the last line of the method, but non-existent attributes or undefined global variables and other things keep crashing the program. I tried making a Radio class from Widget to hold a FloatLayout with Buttons, Knob, and Display, since I thought that would facilitate referencing object, but that has been an utter failure so far.
class Knob_8_Pos(Button):
knob_index = BoundedNumericProperty(0, min=0, max=7, errorvalue=0)
knob_pict = ListProperty(['knob_0.png','knob_1.png','knob_2.png',...])
def __init__(self, **kwargs):
super(Knob_8_Pos, self).__init__(**kwargs)
self.background_normal = 'Images/knob_0.png'
def change_image(self, touch):
self.knob_index += 1
self.background_normal = self.knob_pict[self.knob_index]
self.background_down = 'Images/knob_down.png'
if self.knob_index == 0:
print('Knob_index is zero.')
self.ids[button_0].text = 'Changed'
why not send button0 to the change_image class?
Knob_8_Pos:
id: knob8
size_hint: 0.19,0.35
pos_hint: {'center_x':0.725, 'center_y':0.38}
on_press:
self.change_image(button_0)
And you change its text like this
def change_image(self, button0): # <----
self.knob_index += 1
self.background_normal = self.knob_pict[self.knob_index]
self.background_down = 'Images/knob_down.png'
if self.knob_index == 0:
print('Knob_index is zero.')
button0.text = 'Changed' #<----

Flex Mobile List: How to get rid of grey overlay on renderer tap?

I tried setting all possible styles to something other than grey, just to try and get rid of the grey overlay as shown in the "Hello item 1" in the attached image of a list. Nothing worked. I examined the ListSkin class too and didn't fins anything that would draw these. How to get rid of these overlays?
<s:List id="list" width="100%" height="100%"
dataProvider="{dp}"
focusAlpha="0"
contentBackgroundAlpha="0"
contentBackgroundColor="0xFFFFFF"
selectionColor="0xFFFFFF"
downColor="0xFFFFFF"
borderVisible="false"
>
</s:List>
I just helped a client with this same thing. You, basically, have to extend the LabelItemRemderer class to not draw the rectangle. It is not exposed via styles or colors for you to change.
Look at this code (Starting at line 853 in the LabelItemRemderer):
// Selected and down states have a gradient overlay as well
// as different separators colors/alphas
if (selected || down)
{
var colors:Array = [0x000000, 0x000000 ];
var alphas:Array = [.2, .1];
var ratios:Array = [0, 255];
var matrix:Matrix = new Matrix();
// gradient overlay
matrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0 );
graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
You basically need some way to force this code to not run. You can do this by creating your own itemRenderer from scratch. Or you can extend the LabelItemRenderer, override the drawBackground() method and copy all the parent drawBackground() code into your extended child; minus the block above.
I'd love to see the color exposed as a style or something. I'd love to see a magic property (or style) we could use to make the overlay vanish altogether. Feel free to log this as a bug into the Apache Flex Jira.