It seems that there is no on_click option with dropdown widgets, I was wondering if there is some sort of workaround. One method I was thinking was, everytime an option is chosen, to flush the options and start the dropdown from the top again, where the top option would be the empty "".
For instance suppose I have:
from IPython.html import widgets
from IPython.display import display
def dropdown_event_handler(change):
print(change.new)
# flush the options and start from "" again
options = ["", "A", "B"]
dropdown = widgets.Dropdown(options=options, description="Categories")
dropdown.observe(dropdown_event_handler, names="value")
display(dropdown)
So the desired behaviour is that if I press "A" and "A" again, A would be printed out twice.
As you already suggested, you could set the value of the widget to "" after each change:
from IPython.html import widgets
from IPython.display import display
def dropdown_event_handler(change):
print(change.new)
dropdown.value = ""
options = ["", "A", "B"]
dropdown = widgets.Dropdown(options=options, description="Categories")
dropdown.observe(dropdown_event_handler, names='value')
display(dropdown)
And I fear that is your only option. The Dropdown widget has no other type than "change". You can see all available types by printing them with type=All.
from IPython.html import widgets
from IPython.display import display
from traitlets import All
def dropdown_event_handler(change):
print(change)
options = ["", "A", "B"]
dropdown = widgets.Dropdown(options=options, description="Categories")
dropdown.observe(dropdown_event_handler, type=All)
display(dropdown)
Output:
{'name': '_property_lock', 'old': traitlets.Undefined, 'new': {'index': 1}, 'owner': Dropdown(description='Categories', options=('', 'A', 'B'), value=''), 'type': 'change'}
{'name': 'label', 'old': '', 'new': 'A', 'owner': Dropdown(description='Categories', index=1, options=('', 'A', 'B'), value=''), 'type': 'change'}
{'name': 'value', 'old': '', 'new': 'A', 'owner': Dropdown(description='Categories', index=1, options=('', 'A', 'B'), value='A'), 'type': 'change'}
{'name': 'index', 'old': 0, 'new': 1, 'owner': Dropdown(description='Categories', index=1, options=('', 'A', 'B'), value='A'), 'type': 'change'}
{'name': '_property_lock', 'old': {'index': 1}, 'new': {}, 'owner': Dropdown(description='Categories', index=1, options=('', 'A', 'B'), value='A'), 'type': 'change'}
So you can't observe a value in a Dropdown widget if it did not change. For more information see the Traitlets documentation.
Related
dicta={'name': 'C','children': {'name': 'testA','children': {'name': 'test_file'}}}
dictb={'name': 'C','children': {'name': 'testA','children': {'name': 'test_fileB','children': {'name': 'test_file'}}}}
dictc={'name': 'C','children':[{"name":"testA","children":[{"name":"test_file"},{'name': 'test_fileB','children': {'name': 'test_file'}}]}]}
I want to use dicta and dictb to get dictc;but I don't know how.
You can define a function to merge dictionaries and call it recursively:
def merge(dict1, dict2):
result = {**dict1}
if 'children' in dict1 and 'children' in dict2:
if dict1['children']['name'] == dict2['children']['name']:
result['children'] = [merge(dict1['children'], dict2['children'])]
else:
result['children'] = [dict1['children'], dict2['children']]
elif 'children' in dict1:
result['children'] = [dict1['children']]
elif 'children' in dict2:
result['children'] = [dict2['chidlren']]
else:
del result['children']
return result
dictc = merge(dicta, dictb)
You didn't provide many details on how exactly the merge should work, but this example does produce the dictc as you want. You may need to tweak something for your needs
Is there an equivalent of the CSS z-index for vis.js nodes?
Suppose that I have 2 kinds of nodes (in a graph with physics disabled): Circles and rectangles. I would like the rectangles to always be displayed over the circles when they are overlapping.
Kind of a late reply but the short answer is: no
See this issue: https://github.com/almende/vis/issues/3146
Judging by the mentioned issue, a more precise answer would be: there's no documented way to set z-index (and there's no such concept), but what you can use (with a risk of getting this broken at some update) is nodes are drawn in the same order they are defined. From comment:
I used the following test nodes:
var nodes = [
{id: 'a', label: 'a', shape: 'dot'},
{id: 'b', label: 'b', shape: 'dot'},
{id: 'c', label: 'c', shape: 'dot'},
{id: 'd', label: 'd', shape: 'dot'}
];
When not selected, these will draw in the node order:
Now, let's change the order:
var nodes = [
{id: 'c', label: 'c', shape: 'dot'},
{id: 'b', label: 'b', shape: 'dot'},
{id: 'd', label: 'd', shape: 'dot'},
{id: 'a', label: 'a', shape: 'dot'}
];
I've been trying to enable panning/zooming while the hover tool is enabled using this example - http://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hover-tool. But, I can't seem to get the two to work together.
Are they mutually exclusive tools?
I was specifying the tools in the wrong place. Here's a working example if anyone else is trying to do the same -
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import HoverTool
output_file("toolbar.html")
source = ColumnDataSource(
data=dict(
x=[1,2,3,4,5],
y=[2,5,8,2,7],
desc=['A', 'b', 'C', 'd', 'E'],
)
)
hover = HoverTool(
tooltips = [
("index", "$index"),
("(x,y)", "($x, $y)"),
("desc", "#desc"),
]
)
p = figure(plot_width=400, plot_height=400, tools=[hover, 'pan', 'wheel_zoom'],
title="Mouse over the dots")
p.circle('x', 'y', size=20, source=source)
show(p)
I currently have a QListWidget that displays many items that are user selectable (and dragable). In my application, when an item is checked it will be reordered above the unchecked items. The user can also drag/drop to adjust the order of the checked items.
The problem the users have is that there are a TON of these check boxes and they are not grouped logically on the screen. Thus, I'd like to introduce grouping of some kind. Here is an example of how it currently works.
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
for row in rows:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())
This produces an application like this:
What I want to do is group the items that have similar groups under a similar heading. When an item is checked, it'd appear above the groups. Initially, this looks like a QTreeWidget/View, except that the checked items need to appear outside of the existing tree.
Example (text output):
[CHECKED ITEMS APPEAR HERE]
Group 1
Row1
Row2
Row3
Group 2
Row4
Row5
Row9
Group 3
Row6
Row7
Row8
Group testing
Row10
Is there a way to group items in a QListWidget, preferable so that the 'header' can be selected and all child elements can be autoselected?
to list items in groups here a simalar question: How to list items as groups in QListWidget
if headeritems and normal items are different in one property they can be handled differently in slot.
I'm not quite certain, if it's the way you want. I tried to place checked items on the top and select all items of a group by click on the headeritem.
By selecting another signal and modyfiing the slot there are many possibilities, to change the behaviour. Here my code (i tried it in PyPt5 by replacing QtGui by QtWidgets
from PyQt4 import QtGui, QtCore
import sys
rows = [
{'text': 'Row1', 'value': 1, 'group': 1},
{'text': 'Row2', 'value': 2, 'group': 1},
{'text': 'Row3', 'value': 3, 'group': 1},
{'text': 'Row4', 'value': 4, 'group': 2},
{'text': 'Row5', 'value': 5, 'group': 2},
{'text': 'Row6', 'value': 6, 'group': 3},
{'text': 'Row7', 'value': 7, 'group': 3},
{'text': 'Row8', 'value': 8, 'group': 3},
{'text': 'Row9', 'value': 9, 'group': 2},
{'text': 'Row10', 'value': 10, 'group': 'testing'}
]
grouptitles = [1, 2, 3,'testing'] # list of grouptitles
def gruppe(d): # function for sorting the itemlist
return str(d['group'])
rows.sort(key=gruppe,reverse=False) # sort rows by groups
class MyList(QtGui.QListWidget):
def __init__(self):
QtGui.QListWidget.__init__(self)
self.setMinimumHeight(270)
for t in grouptitles:
item = QtGui.QListWidgetItem('Group {}'.format(t))
item.setData(33, 'header')
item.setData(34, t)
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
self.addItem(item)
for row in rows:
if row['group'] == t:
item = QtGui.QListWidgetItem(row['text'])
# These are utilizing the ItemDataRole; 33 and 34 are among the first user defined values
# http://pyqt.sourceforge.net/Docs/PyQt4/qt.html#ItemDataRole-enum
item.setData(33, row['value'])
item.setData(34, row['group'])
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setCheckState(QtCore.Qt.Unchecked)
self.addItem(item)
else:
pass
self.setSelectionMode(QtGui.QAbstractItemView.MultiSelection) #
self.itemClicked.connect(self.selManager) # select an appropriate signal
def selManager(self, item):
if item.data(33) == 'header':
groupcode = item.data(34)
for i in range(0,self.count()):
if self.item(i).data(34) == groupcode and self.item(i).data(33) != 'header':
b = True if self.item(i).isSelected() == False else False
self.item(i).setSelected(b)
else:
if item.checkState() == QtCore.Qt.Unchecked:
item.setCheckState(QtCore.Qt.Checked)
self.moveItem(self.currentRow(),0)
else:
item.setCheckState(QtCore.Qt.Unchecked)
text = 'Group {}'.format(item.data(34))
new = self.indexFromItem(self.findItems(text, QtCore.Qt.MatchExactly)[0]).row() # find the row of the headeritem
self.moveItem(self.currentRow(), new) # moving back to group
def moveItem(self, old, new): # from row(old) to row(new)
ni = self.takeItem(old)
self.insertItem(new,ni)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
my_list = MyList()
my_list.show()
sys.exit(app.exec_())
I think it is pretty straightforward. All I am trying to do is update the original dictionary's 'code' with that of another dictionary which has the value. I get a feeling 2 for loops and an IF loop can be further shortened to get the answer. In my actual problem, I have few 1000's of dicts that I have to update. Thanks guys!
Python:
referencedict = {'A': 'abc', 'B': 'xyz'}
mylistofdict = [{'name': 'John', 'code': 'A', 'age': 28}, {'name': 'Mary', 'code': 'B', 'age': 32}, {'name': 'Joe', 'code': 'A', 'age': 43}]
for eachdict in mylistofdict:
for key, value in eachdict.items():
if key == 'code':
eachdict[key] = referencedict[value]
print mylistofdict
Output:
[{'age': 28, 'code': 'abc', 'name': 'John'}, {'age': 32, 'code': 'xyz', 'name': 'Mary'}, {'age': 43, 'code': 'abc', 'name': 'Joe'}]
There is no need to loop over all values of eachdict, just look up code directly:
for eachdict in mylistofdict:
if 'code' not in eachdict:
continue
eachdict['code'] = referencedict[eachdict['code']]
You can probably omit the test for code being present, your example list always contains a code entry, but I thought it better to be safe. Looking up the code in the referencedict structure assumes that all possible codes are available.
I used if 'code' not in eachdict: continue here; the opposite is just as valid (if 'code' in eachdict), but this way you can more easily remove the line if you do not need it, and you save yourself an indent level.
referencedict = {'A': 'abc', 'B': 'xyz'}
mylistofdict = [{'name': 'John', 'code': 'A', 'age': 28}, {'name': 'Mary', 'code': 'B', 'age': 32}, {'name': 'Joe', 'code': 'A', 'age': 43}]
for x in mylistofdict:
try:
x['code']=referencedict.get(x['code'])
except KeyError:
pass
print(mylistofdict)