diff --git a/README.md b/README.md index 2a7635e..7237517 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,11 @@ The application window should appear. ## Want to build your own apps? > If you think these apps are neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +PyQt in general, take a look at [my free online tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. -You can also find more PyQt articles, tutorials and projects -[on my website](http://martinfitzpatrick.name/tag/pyqt). +You can also find write-ups about these apps +[here](http://www.learnpyqt.com/apps). ## License diff --git a/browser/README.md b/browser/README.md index da873cc..501eab5 100644 --- a/browser/README.md +++ b/browser/README.md @@ -6,10 +6,9 @@ browsing experience with the usual controls, as well as saving and loading HTML. ![Browser](screenshot-browser.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Other licenses diff --git a/browser/browser.py b/browser/browser.py index 1c18536..797425b 100644 --- a/browser/browser.py +++ b/browser/browser.py @@ -159,7 +159,7 @@ class MainWindow(QMainWindow): "All files (*.*)") if filename: - html = self.browser.page().mainFrame().toHtml() + html = self.browser.page().toHtml() with open(filename, 'w') as f: f.write(html) diff --git a/browser/requirements.txt b/browser/requirements.txt index 0727731..8cb824a 100644 --- a/browser/requirements.txt +++ b/browser/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/browser_tabbed/README.md b/browser_tabbed/README.md index 4dfb3c2..d694f39 100644 --- a/browser_tabbed/README.md +++ b/browser_tabbed/README.md @@ -7,10 +7,9 @@ coincidental. ![Browser tabbed](screenshot-browser-tabbed.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Code notes diff --git a/browser_tabbed/browser_tabbed.py b/browser_tabbed/browser_tabbed.py index 4b8c0fb..3cbbcd6 100644 --- a/browser_tabbed/browser_tabbed.py +++ b/browser_tabbed/browser_tabbed.py @@ -208,7 +208,7 @@ class MainWindow(QMainWindow): "All files (*.*)") if filename: - html = self.tabs.currentWidget().page().mainFrame().toHtml() + html = self.tabs.currentWidget().page().toHtml() with open(filename, 'w') as f: f.write(html.encode('utf8')) diff --git a/browser_tabbed/requirements.txt b/browser_tabbed/requirements.txt index 0727731..8cb824a 100644 --- a/browser_tabbed/requirements.txt +++ b/browser_tabbed/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/calculator/calculator.py b/calculator/calculator.py index ed4e897..9c07e09 100644 --- a/calculator/calculator.py +++ b/calculator/calculator.py @@ -91,10 +91,15 @@ class MainWindow(QMainWindow, Ui_MainWindow): if self.current_op: self.last_operation = self.stack[-1], self.current_op - self.stack = [self.current_op(*self.stack)] - self.current_op = None - self.state = READY - self.display() + try: + self.stack = [self.current_op(*self.stack)] + except Exception: + self.lcdNumber.display('Err') + self.stack = [0] + else: + self.current_op = None + self.state = READY + self.display() if __name__ == '__main__': diff --git a/calculator/requirements.txt b/calculator/requirements.txt index 0727731..8cb824a 100644 --- a/calculator/requirements.txt +++ b/calculator/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/camera/README.md b/camera/README.md index c3f0d50..6849e1c 100644 --- a/camera/README.md +++ b/camera/README.md @@ -7,10 +7,9 @@ them. ![Camera](screenshot-camera.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Other licenses diff --git a/camera/camera.py b/camera/camera.py index e3b948c..3552f68 100644 --- a/camera/camera.py +++ b/camera/camera.py @@ -73,9 +73,6 @@ class MainWindow(QMainWindow): self.save_seq = 0 def take_photo(self): - self.viewfinder.setContrast(100) - #self.viewfinder.setBrightness(0) - timestamp = time.strftime("%d-%b-%Y-%H_%M_%S") self.capture.capture(os.path.join(self.save_path, "%s-%04d-%s.jpg" % ( self.current_camera_name, diff --git a/currency/README.md b/currency/README.md index 8eac8af..a4e493f 100644 --- a/currency/README.md +++ b/currency/README.md @@ -10,10 +10,9 @@ hand panel and updated to follow the position of the mouse. ![Doughnut](screenshot-currency2.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Code notes diff --git a/currency/requirements.txt b/currency/requirements.txt index 20afbba..cbff174 100644 --- a/currency/requirements.txt +++ b/currency/requirements.txt @@ -1,4 +1,5 @@ PyQt5>=5.6 +sip requests>=2.0.0 requests_cache>=0.4.13 pyqtgraph>=0.10 diff --git a/mediaplayer/README.md b/mediaplayer/README.md index 804bf9e..5bd24f7 100644 --- a/mediaplayer/README.md +++ b/mediaplayer/README.md @@ -15,7 +15,6 @@ which floats on top. ![Mediaplayer](screenshot-mediaplayer2.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. \ No newline at end of file diff --git a/mediaplayer/mediaplayer.py b/mediaplayer/mediaplayer.py index 2e51ca7..fe4cc50 100644 --- a/mediaplayer/mediaplayer.py +++ b/mediaplayer/mediaplayer.py @@ -118,15 +118,16 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.model.layoutChanged.emit() - def update_duration(self, mc): - self.timeSlider.setMaximum(self.player.duration()) - duration = self.player.duration() + def update_duration(self, duration): + print("!", duration) + print("?", self.player.duration()) + + self.timeSlider.setMaximum(duration) if duration >= 0: self.totalTimeLabel.setText(hhmmss(duration)) - def update_position(self, *args): - position = self.player.position() + def update_position(self, position): if position >= 0: self.currentTimeLabel.setText(hhmmss(position)) diff --git a/mediaplayer/requirements.txt b/mediaplayer/requirements.txt index 0727731..8cb824a 100644 --- a/mediaplayer/requirements.txt +++ b/mediaplayer/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/minesweeper/README.md b/minesweeper/README.md index 62d6856..beb46a8 100644 --- a/minesweeper/README.md +++ b/minesweeper/README.md @@ -18,10 +18,9 @@ alien bugs (B'ug) but they could just as easily be anything else. ![Moonsweeper](screenshot-minesweeper2.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Code notes diff --git a/minesweeper/requirements.txt b/minesweeper/requirements.txt index 0727731..8cb824a 100644 --- a/minesweeper/requirements.txt +++ b/minesweeper/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/notepad/README.md b/notepad/README.md index 13b0d63..a1e4567 100644 --- a/notepad/README.md +++ b/notepad/README.md @@ -5,7 +5,6 @@ everything. Supports file loading, saving and printing. ![No2Pads](screenshot-notepad.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. \ No newline at end of file diff --git a/notepad/notepad.py b/notepad/notepad.py index 8cd1bc1..10311c2 100644 --- a/notepad/notepad.py +++ b/notepad/notepad.py @@ -125,39 +125,37 @@ class MainWindow(QMainWindow): def file_open(self): path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "Text documents (*.txt);All files (*.*)") - try: - with open(path, 'rU') as f: - text = f.read() + if path: + try: + with open(path, 'rU') as f: + text = f.read() - except Exception as e: - self.dialog_critical(str(e)) + except Exception as e: + self.dialog_critical(str(e)) - else: - self.path = path - self.editor.setPlainText(text) - self.update_title() + else: + self.path = path + self.editor.setPlainText(text) + self.update_title() def file_save(self): if self.path is None: # If we do not have a path, we need to use Save As. return self.file_saveas() - text = self.editor.toPlainText() - try: - with open(self.path, 'w') as f: - f.write(text) - - except Exception as e: - self.dialog_critical(str(e)) + self._save_to_path(self.path) def file_saveas(self): path, _ = QFileDialog.getSaveFileName(self, "Save file", "", "Text documents (*.txt);All files (*.*)") - text = self.editor.toPlainText() if not path: # If dialog is cancelled, will return '' return + self._save_to_path(path) + + def _save_to_path(self, path): + text = self.editor.toPlainText() try: with open(path, 'w') as f: f.write(text) diff --git a/notepad/requirements.txt b/notepad/requirements.txt index 0727731..8cb824a 100644 --- a/notepad/requirements.txt +++ b/notepad/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/notes/README.md b/notes/README.md index 667ca87..b05b8fd 100644 --- a/notes/README.md +++ b/notes/README.md @@ -8,7 +8,6 @@ are stored locally in a SQLite database. This app is very simple, but demonstrates creation of decoration-less windows in PyQt. Removing the window decorations removes the means to drag windows around, so we must re-implement this behaviour ourselves. -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. \ No newline at end of file diff --git a/notes/requirements.txt b/notes/requirements.txt index 0727731..8cb824a 100644 --- a/notes/requirements.txt +++ b/notes/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/paint/README.md b/paint/README.md index 31a7d65..e97e365 100644 --- a/paint/README.md +++ b/paint/README.md @@ -17,10 +17,9 @@ which is pre-loaded with pictures of delicious pie. ![Piecasso](screenshot-paint2.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Code notes diff --git a/paint/paint.py b/paint/paint.py index 8bcc776..36d2b88 100644 --- a/paint/paint.py +++ b/paint/paint.py @@ -402,27 +402,14 @@ class Canvas(QLabel): else: self.active_color = self.secondary_color - # Convert to image for pixel-by-pixel reading. image = self.pixmap().toImage() w, h = image.width(), image.height() - s = image.bits().asstring(w * h * 4) - x, y = e.x(), e.y() - # Lookup the 3-byte value at our current location. - i = (x + (y * w)) * 4 - target_color = s[i:i+3] - # Convert bytestring to 1byte pp. true/false for matching colour. True values - # will be 255, non-matching 0. Simplifies the lookup in get_pixel and - # comparison in the main loop giving slight performance increase. - s = b''.join(b'\xff' if s[n:n+3] == target_color else b'\x00' for n in range(0, len(s), 4)) - - def get_pixel(x, y): - i = (x + (y * w)) - return s[i] + # Get our target color from origin. + target_color = image.pixel(x,y) have_seen = set() - to_fill = [] queue = [(x, y)] def get_cardinal_points(have_seen, center_pos): @@ -439,18 +426,17 @@ class Canvas(QLabel): return points + # Now perform the search and fill. + p = QPainter(self.pixmap()) + p.setPen(QPen(self.active_color)) + while queue: x, y = queue.pop() - if get_pixel(x, y): # 255 for a match (True) or 0 for a miss (False) - to_fill.append((x,y)) + if image.pixel(x, y) == target_color: + p.drawPoint(QPoint(x, y)) queue.extend(get_cardinal_points(have_seen, (x, y))) - if to_fill: - # Now we have the points, perform the fill. - p = QPainter(self.pixmap()) - p.setPen(QPen(self.active_color)) - p.drawPoints(*[QPoint(*xy) for xy in to_fill]) - self.update() + self.update() # Dropper events diff --git a/paint/requirements.txt b/paint/requirements.txt index 0727731..8cb824a 100644 --- a/paint/requirements.txt +++ b/paint/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/solitaire/README.md b/solitaire/README.md index f5494a6..9d20680 100644 --- a/solitaire/README.md +++ b/solitaire/README.md @@ -59,3 +59,8 @@ Note that the linked repository contains some custom art on ace cards which may was not used. Icons used in the application are by [Yusuke Kamiyaman](http://p.yusukekamiyamane.com/). + + +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. \ No newline at end of file diff --git a/solitaire/requirements.txt b/solitaire/requirements.txt index 0727731..8cb824a 100644 --- a/solitaire/requirements.txt +++ b/solitaire/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/translate/README.md b/translate/README.md index c95fca6..11757ce 100644 --- a/translate/README.md +++ b/translate/README.md @@ -1,6 +1,6 @@ # Translatarrrr — Instant translation from any language to Pirate -A translator from any language (supported by Goolge translate) to pirate. +A translator from any language (supported by Google translate) to pirate. This uses a remote API from http://api.funtranslations.com for English to Pirate translation, and a unofficial Python wrapper around Google translate for other languages to English. @@ -19,9 +19,6 @@ pay for an API key to get more. This is, therefore, very useless. -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. - - +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. diff --git a/translate/requirements.txt b/translate/requirements.txt index 7fcec9a..649a08e 100644 --- a/translate/requirements.txt +++ b/translate/requirements.txt @@ -1,2 +1,3 @@ PyQt5>=5.6 +sip requests>=2.0.0 diff --git a/unzip/README.md b/unzip/README.md index 78f54d6..8c28dc7 100644 --- a/unzip/README.md +++ b/unzip/README.md @@ -14,10 +14,9 @@ Simply drag and drop your .zip file onto the cat to fill it up with Pez. The press the cat's head to release the Pez. -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Code notes diff --git a/unzip/requirements.txt b/unzip/requirements.txt index 0727731..8cb824a 100644 --- a/unzip/requirements.txt +++ b/unzip/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/unzip/unzip.py b/unzip/unzip.py index e4255bf..d51d4c1 100644 --- a/unzip/unzip.py +++ b/unzip/unzip.py @@ -56,7 +56,7 @@ class UnzipWorker(QRunnable): items = self.zipfile.infolist() total_n = len(items) - for n, item in enumerate(items): + for n, item in enumerate(items, 1): if not any(item.filename.startswith(p) for p in EXCLUDE_PATHS): self.zipfile.extract(item) @@ -99,7 +99,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): # Perform the unzip self.threadpool.start(self.worker) - self.worker = None # Remove the worker so it is not double-triggere. + self.worker = None # Remove the worker so it is not double-triggered. elif e.button() == Qt.RightButton: pass # Open a new zip. @@ -201,11 +201,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): ) def unzip_finished(self): - self.update_progress(1) + pass def unzip_error(self, err): exctype, value, traceback = err + self.update_progress(1) # Reset the Pez bar. + dlg = QMessageBox(self) dlg.setText(traceback) dlg.setIcon(QMessageBox.Critical) diff --git a/weather/README.md b/weather/README.md index 9a1b1b8..6bb71f3 100644 --- a/weather/README.md +++ b/weather/README.md @@ -5,10 +5,9 @@ weather and forecast API from https://openweathermap.org/ ![Weather](screenshot-weather.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Other licenses diff --git a/weather/requirements.txt b/weather/requirements.txt index 7fcec9a..649a08e 100644 --- a/weather/requirements.txt +++ b/weather/requirements.txt @@ -1,2 +1,3 @@ PyQt5>=5.6 +sip requests>=2.0.0 diff --git a/wordprocessor/README.md b/wordprocessor/README.md index e623b36..d8c0077 100644 --- a/wordprocessor/README.md +++ b/wordprocessor/README.md @@ -12,10 +12,9 @@ Saves and opens HTML format documents. ![Wordprocessor](screenshot-wordprocessor.jpg) -> If you think this example app is neat and want to learn more about -PyQt in general, [take a look at my ebook & online course -"Create Simple GUI Applications"](https://martinfitzpatrick.name/create-simple-gui-applications) -which covers everything you need to know to start building your own applications with PyQt. +> If you think this app is neat and want to learn more about +PyQt in general, take a look at my [free PyQt tutorials](https://www.learnpyqt.com) +which cover everything you need to know to start building your own applications with PyQt. ## Other licenses diff --git a/wordprocessor/requirements.txt b/wordprocessor/requirements.txt index 0727731..8cb824a 100644 --- a/wordprocessor/requirements.txt +++ b/wordprocessor/requirements.txt @@ -1 +1,2 @@ PyQt5>=5.6 +sip diff --git a/wordprocessor/wordprocessor.py b/wordprocessor/wordprocessor.py index 3540b9a..2186489 100644 --- a/wordprocessor/wordprocessor.py +++ b/wordprocessor/wordprocessor.py @@ -68,7 +68,6 @@ class MainWindow(QMainWindow): layout = QVBoxLayout() self.editor = TextEdit() # Setup the QTextEdit editor configuration - self.editor.setAcceptRichText(False) self.editor.setAutoFormatting(QTextEdit.AutoAll) self.editor.selectionChanged.connect(self.update_format) # Initialize default font size.