Welcome to Update 3 of the Dicecord project. This weekend I was unable to complete all my goals due to an injury, but I got a lot of the main work done at least. I finished off the Health widget, I made a Mana widget and I finished a class of widget that will serve as the foundation for the remaining parts of the main sheet. As always, the latest code can be found here on my github repo.
As stated last time, I created a general health widget but I needed to add the logic for cycling through damage types; left click would cycle up and right click would cycle down. While the left click cycle was easy enough to code, the right click cycle was surprisingly tricky. It appears that there is no specific right click signal in PyQt5; it seems hard coded into the action to bring up a right click context menu. So in order to specify a right click signal I had to enable a custom context menu policy on the widget but then connect the request context menu action to a handler function. Sample code do to so is reproduced below.
from PyQt5.QtWidgets import * from PyQt5.QtCore import * import sys class Right_Click (QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): box = QVBoxLayout() self.setLayout(box) button = QPushButton('Example') button.clicked.connect(self.left) #Right click button.setContextMenuPolicy(Qt.CustomContextMenu) button.customContextMenuRequested.connect(self.right) box.addWidget(button) def right(self): print("right") def left(self): print("left") if __name__ == '__main__': app = QApplication(sys.argv) test = Right_Click() test.show() sys.exit(app.exec_())
Using the code above, a left click will print “left” to the console, a right click will print “right” to it.
Higher damage types fill the earlier boxes first, so after setting the new rating a loop runs that checks the boxes before and after the click. Everything before must be equal to or higher than the clicked box’s new rating, everything after must be equal to or less than it. If any boxes don’t fulfill these criteria they are set to the same rating as the clicked box.
After playing around with some options I ended up using a system similar to the derived stats for Mana. The UI shows you your current mana/total mana and you enter in how much you have spent in a spinner box. I’m not too happy though with how this looks and I may experiment with other means of displaying this. One option I am thinking of is maybe a bar that you fill or empty instead. This will add a bit of colour to the sheet and allow for splat level customization. For example, Mana would be blue, but Blood could be red and Glamour could be green.
Hover Text Label
This has turned out to be one of the more complex things to set up, however once it is finished it will be a widget I can use in a lot of places. It is basically a label that can optionally have a tooltip that gives extra context on hover. In the case of merits and pretty much the entire bottom half of the rightmost column user will be able to add entire new entries or edit existing ones.
One of the tricks to this turned out to be creating a custom QDialog widget for entry of new content. This widget has a grid layout where you enter two inputs (the title + the tooltip) and three buttons (Save, Cancel, Delete). Getting the output from the two input fields was easy enough, but a more difficult feature was adding the third button. You see, the QDialog widget has a bunch of default buttons, however only two methods that close the dialog and send a response: accept() and reject(). When trying to find tutorials that explain more complex QDialogs I found people talking about “reset” and “clear” functions that interact with the contents of the dialog, but nothing that closes it and sends another signal. In order to get the functionality I needed I had to set a handle function for the “Delete” button that sets the content of the input to
####DELETE#### and then sends the accept() response. Then I can make my function for processing the output of the dialog follow the delete steps if it reads
####DELETE#### as the new title.
If that sounds complicated, worry not, I plan to go over this in detail in a later tutorial.
I managed to make time for a UI sweep during the week. At first I tried doing each column as a separate Vertical Box Layout that I then organised in a Horzontal Box Layout but I had strange behaviour with widget Alignments. Generally it became impossible for the derivatives section in the middle row to be forced to the bottom since the middle layout did not fit to the screen. Trying to make it do so resulted in the Arcana widget hovering in the middle rather than sticking to the bottom of the attributes up top.
In the end I went for a compromise where the first column is a single widget stretched over multiple grid rows, the last column is a vertical box stretched over grid rows and the middle are widgets in specific grids. As the grid sizes are defined by the biggest widget in the grid, this allows more power over the alignment of each specific widget. Another issue with alignment I had was that the merit object would change size depending on the largest merit title length; for short named merits the dots were close to the left side rather thasn justified right like the other stats. After some experimenting I discovered that moving the delete button from the right hand side to the left hand side allowed the widget extend all the way to the right.
In terms of the big dot sizes, some napkin math puts a radius of 12-14 pixels as being a better size and should allow the 12 dot health object match the standard width of the attributes object. I will experiment more with this if I have time over the coming week.
Plans for Next Week
I am finished my night shift rotation at work now, so I will get time in my evenings to dedicate more work. However, our mage game is also getting close to starting so I have to juggle my time prepping for that too.
- Finish Hover Text Label
- Add Obsessions, Aspirations, Conditions and Tilts
- Add skill specialities
- Change merits to make use of Hover text Labels
- Get started on import/export character methods