当前位置: 首页 > 编程日记 > 正文

如何使用Python和Tkinter构建Toy Markdown编辑器

Markdown editors are trending these days. Everybody is creating a markdown editor, and some of them are innovative while some of them are boring.

Markdown编辑器近来呈趋势。 每个人都在创建降价编辑器,其中有些人很创新,而有些人很无聊。

As for myself, however, I have always been a fan of doing things which haven't been done by others. (I will explain below why other devs don't want to build a markdown editor with Tkinter.)

至于我自己,我一直热衷于做别人没有做过的事情。 (我将在下面解释为什么其他开发人员不想使用Tkinter构建markdown编辑器。)

If you already are familiar with Python and Tkinter you can easily get into this guide.

如果您已经熟悉Python和Tkinter,则可以轻松阅读本指南。

But If you are just starting out with Python and/or Tkinter, you can check out these: Python Tutorials: FreeCodeCamp Python Tutorial , Python 3 Playlist by sentdex , FreeCodeCamp Python for Beginners etc. (More can be found one Google search away) Tkinter Tutorials: Tkinter Basics , FreeCodeCamp Tkinter Course , TheNewBoston Tkinter Playlist etc. (More can be found one Google search away)

但是,如果您只是刚开始使用Python和/或Tkinter,则可以查看以下内容: Python教程: FreeCodeCamp Python教程 , senddex的 Python 3播放列表 , FreeCodeCamp Python初学者等。(更多内容可以从Google搜索中找到) Tkinter教程: Tkinter基础知识 , FreeCodeCamp Tkinter课程 , TheNewBoston Tkinter播放列表等。(可以在Google搜索中找到更多内容)

So, before we start, I want to explain why people don't want to build markdown editors with tkinter. It's because there's no default easy way to display the html output of the markdown input. There's not even a default tkinter widget to display html data. You can just simply write/edit markdown, but there's no easy way to display the output inside your application.

因此,在开始之前,我想解释一下为什么人们不希望使用tkinter构建markdown编辑器。 这是因为没有默认的简单方法来显示markdown输入的html输出。 甚至没有默认的tkinter小部件来显示html数据。 您可以简单地编写/编辑markdown,但是没有简单的方法可以在应用程序中显示输出。

But one day, while I was roaming the streets of the Internet, I found something interesting: tk_html_widgets. It can display html output!

但是有一天,当我在互联网上漫游时,发现了一些有趣的东西: tk_html_widgets 。 它可以显示html输出!

But ofcourse it did have some problems: the fonts were too small, and it had no support for attaching remote photos. So as usual I created my own fork and fixed some issues and kinda improved the stability. I named it tkhtmlview. 😎

但是当然它确实存在一些问题:字体太小,并且不支持附加远程照片。 因此,像往常一样,我创建了自己的fork,并修复了一些问题,并提高了稳定性。 我将其命名为tkhtmlview 。 😎

Ugh, I think I'm boring you 😅, so let's stop talking and start building.

gh,我想我很无聊,所以让我们停止交谈,开始建设。

Start️开始建设: (🛠️ Start Building:)

First make sure you have Python 3 and Tkinter installed. If not you can download them from here: python.org/downloads (Tkinter is already packed with Python).

首先,请确保您已安装Python 3和Tkinter。 如果不是,您可以从以下位置下载它们: python.org/downloads (Tkinter已经包含Python)。

Other Things we will need are tkhtmlview and markdown2. You can install them by running pip install tkhtmlview markdown2 or pip3 install tkhtmlview markdown2 (if you have multiple versions of Python).

我们需要的其他东西是tkhtmlviewmarkdown2 。 您可以通过运行pip install tkhtmlview markdown2pip3 install tkhtmlview markdown2来安装它们(如果您有多个Python版本)。

Now fire up your favorite editor or IDE and create a new file (eg. tdown.py (I named the editor tdown)). We will start by importing the necessary libraries.

现在启动您喜欢的编辑器或IDE并创建一个新文件(例如tdown.py (我将其命名为tdown编辑器))。 我们将从导入必要的库开始。

from tkinter import *
from tkinter import font , filedialog
from markdown2 import Markdown
from tkhtmlview import HTMLLabel

In the first line we import everything (almost) from the tkinter package.

在第一行中,我们(几乎)从tkinter包中导入所有内容。

In the second line we import the font and filedialog. font is needed to style (eg. Font , Font Size) our input field, and filedialog is imported to open markdown files for editing (and/or for saving our markdown file).

在第二行中,我们导入字体和文件对话框。 需要使用font来设置输入字段的样式(例如Font,Font Size),并导入filedialog以打开markdown文件以进行编辑(和/或保存我们的markdown文件)。

In the 3rd line, Markdown is imported to help us convert our markdown source to html and display it in the output field using HTMLLabel (which we import on the 4th line).

在第三行中,导入了Markdown,以帮助我们将markdown源转换为html,并使用HTMLLabel(在第四行中导入)将其显示在输出字段中。

After that, we will create a frame class called Window which will be inherited from tkinters's Frame class. It will hold our input and output fields.

之后,我们将创建一个名为Window的框架类,该框架类将从tkinters的Frame类继承。 它将保存我们的输入和输出字段。

class Window(Frame):def __init__(self, master=None):Frame.__init__(self, master)self.master = masterself.myfont = font.Font(family="Helvetica", size=14)self.init_window()def init_window(self):self.master.title("TDOWN")self.pack(fill=BOTH, expand=1)

Here in this codeblock, we first define a class called Window which inherits tkinter's Frame widget class.

在此代码块中,我们首先定义一个称为Window的类,该类继承tkinter的Frame小部件类。

Now in the initialization function we take master as a argument which will serve as the parent of the frame. In the next line we initialize a Frame.

现在,在初始化函数中,我们将master作为参数,它将用作框架的父级。 在下一行中,我们初始化一个Frame。

Next we declare a custom font object called self.myfont with the font family Helvetica (you can choose any font family you want) and size 14 which will be used in our markdown input field.

接下来,我们声明一个名为self.myfont的自定义字体对象,其字体家族为Helvetica (您可以选择任何字体家族),尺寸为14 ,将在我们的markdown输入字段中使用。

Finally we call the init_window function where we will put the heart of our application.

最后,我们调用init_window函数,将其放在应用程序的心脏中。

In the init_window function we first set the title of the window as TDOWN. In the next line self.pack(fill=BOTH, expand=1) , we tell our Frame to take the full space of our window.

init_window函数中,我们首先将窗口的标题设置为TDOWN 。 在下一行self.pack(fill=BOTH, expand=1) ,我们告诉Frame占用窗口的全部空间。

We set the fill keyword argument to BOTH which is actually being imported from the tkinter library. It tells the frame to fill the window both horizontally and vertically, and the expand keyword argument is set to 1 (signifies True) which tells our Frame to be expandable. In simple terms the Frame will fill the window no matter how we stretch the window size or maximize it.

我们将fill关键字参数设置为BOTH ,这实际上是从tkinter库导入的。 它告诉框架在水平和垂直方向上都填充窗口,并且expand关键字参数设置为1(表示True ),这告诉我们框架是可扩展的。 简而言之,无论我们如何拉伸或最大化窗口,框架都会填充窗口。

Now if you run the tdown.py script you'll not see anything because we have only defined the class but never called it.

现在,如果您运行tdown.py脚本,您将看不到任何内容,因为我们仅定义了该类,但从未调用过它。

To fix this we are gonna put this at the end of our script:

要解决此问题,我们将其放在脚本的末尾:

root = Tk()
root.geometry("700x600")
app = Window(root)
app.mainloop()

Here we create a Tk object and store it in the root variable which will serve as the root of our Window class.

在这里,我们创建一个Tk对象,并将其存储在root变量中,该变量将用作Window类的根。

Next we set the geometry of our window to 700x600 - 700 is the height and 600 is tthe width of the window. In the next line you can see that we are creating a Window object. We push the root variable as root of the frame and store it in a variable called app.

接下来,将窗口的几何形状设置为700x600-700是窗口的高度,600是窗口的宽度。 在下一行中,您可以看到我们正在创建一个Window对象。 我们将变量推入框架的 ,并将其存储在名为app的变量中。

The next thing we do is just call the mainloop function which tells our app to run! 😊

接下来要做的就是调用mainloop函数,该函数告诉我们的应用程序运行! 😊

Now run the tdown.py script. You will see a blank window like this if you did everything correctly:

现在运行tdown.py脚本。 如果正确完成所有操作,您将看到一个空白窗口:

Blank Tkinter Frame

But it's just a blank window. To write something in the window we need to add a Text Field where we will write our markdown. To do that we are gonna use the Text widget from tkinter.

但这只是一个空白窗口。 要在窗口中写入内容,我们需要添加一个文本字段,在其中写入我们的降价。 为此,我们将使用tkinter中的Text小部件。

...
def init_window(self):self.master.title("TDOWN")self.pack(fill=BOTH, expand=1)self.inputeditor = Text(self, width="1")self.inputeditor.pack(fill=BOTH, expand=1, side=LEFT)

Don't get confused with the ... (three dots) , I put them there only to signify that there are multiple lines of code before this code block.

不要与...混淆(三个点),我将它们放在那里只是为了表示此代码块之前有多行代码。

Here we create a Text widget with a width of 1. Don't scratch your head - here sizes are done using ratios. You'll understand it more clearly in next few seconds when we put in the output box. 😁

在这里,我们创建一个宽度为1的Text小部件。 不要挠头-这里的尺寸是按比例确定的。 当我们将其放入输出框中时,您将在接下来的几秒钟内更清楚地了解它。 😁

We then pack it into the Frame and tell it to be both Horizontally and Vertically stretchable.

然后,我们将其包装到框架中,并使其在水平和垂直方向上均可拉伸。

When you run the script, you'll see that a Multiline Input Field has taken over our whole World Window. If you start writing in it, you may notice that the characters are so tiny!

运行脚本时,您会看到“多行输入字段”已接管了整个“ 世界窗口”。 如果您开始写它,您可能会注意到字符太小了!

Input Field Has Taken Over the Whole Window!

I already knew this problem would arise. That's why I told you earlier to create a custom font object (self.myfont). Now if you do something like this:

我已经知道会出现这个问题。 这就是为什么我之前告诉过您创建自定义字体对象( self.myfont )的原因。 现在,如果您执行以下操作:

self.inputeditor = Text(self, width="1" , font=self.myfont)

(Here, we tell our Text widget to use our custom font instead of the default tiny one!)

(在这里,我们告诉我们的Text小部件使用我们的自定义字体,而不是默认的小字体!)

...the font size of the input field will be increased to 14. Run the script to check if everything worked perfectly.

...输入字段的字体大小将增加到14。运行脚本以检查是否一切正常。

Font Size has been increased to 14

Now, I think it's time to add the outputbox where we will see the html output of our markdown source while we write.

现在,我认为是时候添加outputbox了,我们在编写时将看到markdown源的html输出。

To do that we are gonna add an HTMLLabel, something like this inside init_window function:

为此,我们要添加一个HTMLLabel,在init_window函数中是这样的:

self.outputbox = HTMLLabel(self, width="1", background="white", html="<h1>Welcome</h1>")
self.outputbox.pack(fill=BOTH, expand=1, side=RIGHT)
self.outputbox.fit_height()

We use HTMLLabel from tkhtmlview with a width of 1 (again). We set the width to 1 because the window will be shared between Input Field and Output Box with ratio of 1:1 (You'll understand what I mean when you run the script).

我们使用tkhtmlview中的 HTMLLabel ,宽度为1 (再次)。 我们将宽度设置为1,因为窗口将在输入字段和输出框之间以1:1的比例共享(运行脚本时您会明白我的意思)。

The html keyword argument stores the value which will be shown the first time.

html关键字参数存储将在第一次显示的值。

Then we pack it in the window with side as RIGHT to put it in the right side of the Input Field. The fit_height() makes the texts fit inside the widget (as far as I know... 😁)

然后,将其打包在窗口中,其sideRIGHT以将其置于输入字段的右侧。 fit_height()使文本适合小部件内(据我所知...😁)

Now run the code.

现在运行代码。

Output Box Added!

Now if you start writing in the input field, you may be disappointed (but don't be!) to see that the output is not getting updated as we type. That's because we have not told our program to do so yet.

现在,如果您开始在输入字段中书写,您可能会感到失望(但不要这样!),因为我们输入时输出不会得到更新。 那是因为我们还没有告诉我们的程序这样做。

To do that we are gonna first bind a event with our editor. Then whenever the text is modified the output will be updated, something like this:

为此,我们将首先将事件与编辑器绑定。 然后,无论何时修改文本,输出都会更新,如下所示:

self.inputeditor.bind("<<Modified>>", self.onInputChange)

Put that line inside the init_window() function.

将该行放入init_window()函数中。

So basically that line tells the inputeditor to call the onInputChange function whenever the text is changed. But as we don't have that function yet, we need to write it.

因此,基本上,该行告诉输入inputeditor只要更改文本就调用onInputChange函数。 但是因为我们还没有该功能,所以我们需要编写它。

...
def onInputChange(self , event):self.inputeditor.edit_modified(0)md2html = Markdown()self.outputbox.set_html(md2html.convert(self.inputeditor.get("1.0" , END)))

In the first line, using edit_modified(0) we reset the Modified flag so that it can be reused. Otherwise, after the first event call, it will not work anymore.

在第一行中,使用edit_modified(0)重置Modified标志,以便可以重用它。 否则,在第一个事件调用之后,它将不再起作用。

Next we create a Markdown object named md2html. On the last line, where first we.... wait! The last line may be confusing for some readers. So let me it break it down into three lines.

接下来,我们创建一个名为md2html的Markdown对象。 在最后一行,我们首先在哪里……等待! 最后一行可能会使某些读者感到困惑。 因此,让我将其分为三行。

markdownText = self.inputeditor.get("1.0" , END)
html = md2html.convert(markdownText)
self.outputbox.set_html(html)

Here in the first line we fetch the markdown text from top to bottom of the input field. The first argument, self.inputeditor.get, tells it to start scanning from the first line's 0th character (1.0 => [LINE_NUMBER].[CHARACTER_NUMBER]) , and the last argument tells it to stop scanning it has when reached the end.

在第一行中,我们从输入字段的顶部到底部获取markdown文本。 第一个参数self.inputeditor.get告诉它从第一行的第0个字符开始扫描(1.0 => [LINE_NUMBER]。[CHARACTER_NUMBER]),最后一个参数告诉它停止扫描,直到结束为止。

Then we convert the scanned markdown text to html using the md2html.convert() function and store it in the html variable.

然后,我们使用md2html.convert()函数将扫描的markdown文本转换为html并将其存储在html变量中。

Finally we tell outputbox to display the output using the .set_html() function!

最后,我们告诉outputbox使用.set_html()函数显示输出!

Run the script. You will see a functioning (almost) markdown editor. As you type in the input field, the output will also be updated!

运行脚本。 您将看到一个正常运行的(几乎)降价编辑器。 在输入字段中键入时,输出也将更新!

But...our work is not yet finished. Users need to be able to at least open and save their text.

但是...我们的工作尚未完成。 用户需要至少能够打开并保存其文本。

To do that, we are gonna add a File menu in the menubar. This is where users will be able to open and save files as well as quit the application.

为此,我们将在菜单栏中添加“ File ”菜单。 用户可以在此处打开和保存文件以及退出应用程序。

In the init_window function we will add these lines:

init_window函数中,我们将添加以下行:

self.mainmenu = Menu(self)
self.filemenu = Menu(self.mainmenu)
self.filemenu.add_command(label="Open", command=self.openfile)
self.filemenu.add_command(label="Save as", command=self.savefile)
self.filemenu.add_separator()
self.filemenu.add_command(label="Exit", command=self.quit)
self.mainmenu.add_cascade(label="File", menu=self.filemenu)
self.master.config(menu=self.mainmenu)

I'll make this quick:

我将快速介绍一下:

Here we define a new menu with Frame as its parent.

在这里,我们定义了一个以Frame为父菜单的新菜单。

Next, we define another menu and previous menu as its parent. It will serve as our File menu.

接下来,我们定义另一个菜单,并将上一个菜单作为其父菜单。 它将用作我们的“ File菜单。

Then we add 3 sub menus (Open, Save as, and Exit) and a separator using the add_command() and add_separator() functions. The Open sub-menu will execute the openfile function, the Save as sub-menu will execute the savefile function. and finally Exit will execute a builtin function quit which will close the program.

然后,我们使用add_command()add_separator()函数添加3个子菜单(打开,另存为和退出)和分隔符。 打开子菜单将执行openfile函数, 另存为子菜单将执行savefile函数。 最后, Exit将执行内置函数quit ,它将关闭程序。

Then using the add_cascade() function we tell the first Menu object to include the filemenu variable. This includes all our sub-menus with the label File.

然后使用add_cascade()函数,告诉第一个Menu对象包括filemenu变量。 这包括所有带有标签File子菜单。

At last we use self.master.config() to tell our window to use mainmenu as our window's menubar.

最后,我们使用self.master.config()告诉窗口使用mainmenu作为窗口的菜单栏。

Menu Added

It will look something like this, but don't run it yet. You'll get errors saying that the openfile & savefile functions aren't defined.

它将看起来像这样,但请不要运行它。 您会得到错误消息,提示未定义openfilesavefile函数。

As you can see now, we have to define two functions inside the Window class where we will use tkinter's filedialog.

如您现在所见,我们必须在Window类中定义两个函数,在这里我们将使用tkinter的filedialog。

First Let's define the function to open files:

首先让我们定义打开文件的功能:

def openfile(self):openfilename = filedialog.askopenfilename(filetypes=(("Markdown File", "*.md , *.mdown , *.markdown"),("Text File", "*.txt"), ("All Files", "*.*")))if openfilename:try:self.inputeditor.delete(1.0, END)self.inputeditor.insert(END , open(openfilename).read())except:print("Cannot Open File!")

Here, at first we show the user a file browser dialog that allows them to choose a file to open using filedialog.askopenfilename(). With the filetypes keyword argument we tell the dialog to only open these types of files by passing a tuple with supported files (basically all types of files):

在这里,首先,我们向用户显示一个文件浏览器对话框,允许他们使用filedialog.askopenfilename()选择要打开的文件。 使用filetypes关键字参数,我们告诉对话框仅通过传递带有支持的文件(基本上是所有类型的文件)的元组来打开这些类型的文件:

  • Markdown files with .md , .mdown , .markdown extensions,

    具有.md.mdown.markdown扩展名的Markdown文件,

  • Text Files with .txt extension,

    扩展名为.txt文本文件,

  • and in the next row using a wildcard extension, we tell the dialog to open files with any extension.

    然后在下一行使用通配符扩展名,告诉对话框打开具有任何扩展名的文件。

Then we check if the user has selected a file or not. If yes, we try to open the file. Then we delete all the text inside the input field from the first line's 0th character to the END of the field.

然后,我们检查用户是否选择了文件。 如果是,我们尝试打开该文件。 然后,我们删除输入字段中从第一行的第0个字符到该字段的末尾的所有文本。

Next we open and read the content of the selected file and insert the contents in the input field.

接下来,我们打开并读取所选文件的内容,然后将内容插入输入字段中。

If our program can't open a file it will print out the error. But wait, that's not a good way to handle errors. What we can do here is show an Error Message to the user that looks like this:

如果我们的程序无法打开文件,它将打印出错误。 但是,等等,这不是处理错误的好方法。 我们在这里可以做的是向用户显示一条错误消息,如下所示:

Showing an Error Message

To do that, we are gonna first import messagebox from the tkinter package.

为此,我们首先要从tkinter包中导入messagebox

from tkinter import messagebox as mbox

Then instead of just printing an error message like we did above, we're gonna replace that line with the below line to show a proper error message to the user.

然后,我们不仅要像上面那样打印错误消息,还要用下面的行替换该行,以向用户显示正确的错误消息。

mbox.showerror("Error Opening Selected File" , "Oops!, The file you selected : {} can not be opened!".format(openfilename))

This will create an Error message like the above screenshot I showed you when the file can not be opened.

当无法打开文件时,这将产生一条错误消息,如上面的屏幕截图所示。

In the mbox.showerror function, the first argument is the title of the messagebox. The second one is the message to be displayed.

mbox.showerror函数中,第一个参数是消息框的标题。 第二个是要显示的消息。

Now, we need to write a savefile function to save our markdown input.

现在,我们需要编写一个savefile函数来保存我们的markdown输入。

def savefile(self):filedata = self.inputeditor.get("1.0" , END)savefilename = filedialog.asksaveasfilename(filetypes = (("Markdown File", "*.md"),("Text File", "*.txt")) , title="Save Markdown File")if savefilename:try:f = open(savefilename , "w")f.write(filedata)except:mbox.showerror("Error Saving File" , "Oops!, The File : {} can not be saved!".format(savefilename))

Here at first we scan all the content of the input field and store it in a variable. Then we ask the user for the filename where they want to save the contents by giving the option for two types of file types (.md and .txt).

首先,我们在这里扫描输入字段的所有内容,并将其存储在变量中。 然后,我们通过为两种文件类型(.md和.txt)提供选项,要求用户输入文件名,并将其保存在文件中。

If the user chooses a filename we try to save the contents of the input field stored in the variable filedata. If an exception occurs, we show the user an error message stating that the program wasn't able to save the file.

如果用户选择文件名,我们将尝试保存存储在变量filedata中的输入字段的内容。 如果发生异常,我们会向用户显示一条错误消息,指出该程序无法保存文件。

Don't forget to test your application to check for any bugs! If you and I haven't made any mistakes, our programs should run perfectly and shouldlook something like this:

不要忘记测试您的应用程序以检查任何错误! 如果您和我没有犯任何错误,那么我们的程序应该可以完美运行并看起来像这样:

Final Product

Full source code for this 'tdown' markdown editor is available at GitHub and also at Repl.it where you can test the editor on your browser!

这个“ tdown”降价编辑器的完整源代码可以在GitHub上找到 ,也可以在Repl.it上找到 ,您可以在浏览器上测试该编辑器!

We Finally Did it!

If you get into any problems as you're going through this article you can let me know in the comments or DM me on twitter at @bauripalash.

如果您在阅读本文时遇到任何问题,可以在评论中让我知道,或者在Twitter上@bauripalash DM上发给我。

一些注意事项: (Some Notes:)

  • First, remember that this is just a toy editor. If you want to build more powerful editor you can use any other GUI libraries such as wxPython, PyQT , Kivy and many more which at least have better html support (Full List).

    首先,请记住,这只是一个玩具编辑器。 如果您想构建更强大的编辑器,则可以使用任何其他GUI库,例如wxPython,PyQT,Kivy等,它们至少具有更好的html支持( 完整列表 )。

  • In this article I only showed how to build a basic editor. You can also add many more cool features of your own such as exporting as HTML or PDF, adding buttons to simplify writing Markdown... etc etc.

    在本文中,我仅展示了如何构建基本编辑器。 您还可以添加自己的许多更酷的功能,例如导出为HTML或PDF,添加按钮以简化Markdown编写等。

  • The HTML Rendering modules tkhtmlview or tk_html_widgets are not fully stable and only support some basic html functionalities, so don't expect much.

    HTML渲染模块tkhtmlview或tk_html_widgets并不完全稳定,仅支持一些基本的html功能,因此不要期望太多。

So... I hope you enjoyed this article and learned some new things. Don't forget to let me know if you are stuck somewhere or can't understand something.

所以...希望您喜欢这篇文章并学到一些新东西。 如果您被困在某个地方或听不懂某事,请不要忘了告诉我。

Last but not Least, please Let me know if I made any mistakes above. And I'd love to hear your ideas or suggestions via comments or DM.

最后但并非最不重要,如果我在上面犯了任何错误,请告诉我。 我很乐意通过评论或DM听到您的想法或建议。

Thank You. 👻

谢谢。 👻

翻译自: https://www.freecodecamp.org/news/lets-create-a-toy-markdown-editor-with-python-tkinter/

相关文章:

Hadoop 分布式环境搭建

1.集群机器&#xff1a; 1台 装了 ubuntu 14.04的 台式机 1台 装了ubuntu 16.04 的 笔记本 &#xff08;机器更多时同样适用&#xff09; 搭建步骤&#xff1a; 准备工作&#xff1a; 使两台机器处于同一个局域网&#xff1a;相互能够 ping 通 主机名称 …

常见报错——Uncaught TypeError: document.getElementsByClassName(...).addEventListener is not a function...

这是因为选择器没有正确选择元素对象 document.getElementsByClassName(...)捕捉到的是该类名元素的数组 正确的访问方式应该是&#xff1a; document.getElementsByClassName(...)[0].addEventListener... 使用遍历为每个class添加监听&#xff1a; var classObj document.ge…

uniapp富文本兼容视频实现方案

使用 mp-html 富文本插件&#xff0c;就可以支持富文本内的视频播放。 安装&#xff1a; npm install mp-html 使用方法 <template><view><mp-html :content"html" /></view> </template> <script>import mpHtml from /comp…

循环神经网络 递归神经网络_如何用递归神经网络预测空气污染

循环神经网络 递归神经网络After the citizen science project of Curieuze Neuzen, I wanted to learn more about air pollution to see if I could make a data science project out of it. On the website of the European Environment Agency, you can find a huge amount…

mysql like 命中索引

反向索引案例&#xff1a;CREATE TABLE my_tab(x VARCHAR2(20)); INSERT INTO my_tab VALUES(abcde); COMMIT;CREATE INDEX my_tab_idx ON my_tab(REVERSE(x)); SELECT * FROM my_tab t WHERE REVERSE(t.x) LIKE REVERSE(%cde);//避免使用like时索引不起作用 修改反向索引为正…

CSS超出隐藏并且能滚动

效果图 实现CSS代码&#xff1a; height: 500rpx; overflow-x: hidden; overflow-y: scroll; 效果图的代码&#xff1a; <!-- 豆豆明细弹窗 --><view class"mxBoom" v-show"mxBoom"><view class"mxBoomContent"><view c…

Oracle学习之段区块初步概念

段&#xff1a;一张表可以视为一个段 区&#xff1a;Oracle 给段分配空间的最小单位&#xff0c;表建好后&#xff0c;Oracle就会给表分配物理上连续的空间&#xff0c;叫做区 块&#xff1a;Oracle IO的最小单位&#xff0c;buffer cache中缓存的是dbf文件&#xff0c;由于dbf…

github充当服务器_如何创建充当链接HTML按钮

github充当服务器Sometimes you may want to use a button to link to another page or website rather than to submit a form or something like that. This is fairly simple to do and can be achieved in several ways.有时&#xff0c;您可能希望使用按钮链接到另一个页面…

provide和inject,Vue父组件直接给孙子组件传值

Provide / Inject 该页面假设你已经阅读过了组件基础。如果你还对组件不太了解&#xff0c;推荐你先阅读它。 通常&#xff0c;当我们需要从父组件向子组件传递数据时&#xff0c;我们使用 props。想象一下这样的结构&#xff1a;有一些深度嵌套的组件&#xff0c;而深层的子组…

用欧几里得算法求最大公约数_欧几里得算法:GCD(最大公约数),用C ++和Java示例解释...

用欧几里得算法求最大公约数For this topic you must know about Greatest Common Divisor (GCD) and the MOD operation first.对于本主题&#xff0c;您必须首先了解最大公约数(GCD)和MOD操作。 最大公约数(GCD) (Greatest Common Divisor (GCD)) The GCD of two or more in…

eclipse 重启/打开内置浏览器

重启 Eclipse 重启选项允许用户重启 Eclipse。 我们可以通过点击 File 菜单选择 Restart 菜单项来重启 Eclipse。 Eclipse 内置浏览器 Web 浏览器 Eclipse 系统内部自带了浏览器&#xff0c;该浏览器可以通过点击 Window 菜单并选择 Show View > Other&#xff0c;在弹出来的…

JConsole的使用

一、JConsole是什么 从Java 5开始 引入了 JConsole。JConsole 是一个内置 Java 性能分析器&#xff0c;可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole&#xff08;或者&#xff0c;它更高端的 “近亲” VisualVM &#xff09;来监控 Java 应用程序性能和跟踪 …

折线图表动画(历史进程效果)

代码环境:uniapp 秋云uCharts图表组件https://demo.ucharts.cn/#/代码说明: 在插件市场导入插件秋云 ucharts echarts 高性能跨全端图表组件 - DCloud 插件市场uCharts v2.3上线,支持nvue!全新官方图表组件,支持H5及APP用ECharts渲染图表,uniapp可视化首选组件

不要只是为您的代码做些毛-用Prettier修复它

Linting makes our lives easier because it tells us what’s wrong with our code. But how can we avoid doing the actual work that goes into fixing it?Linting使我们的生活更轻松&#xff0c;因为它告诉我们代码有什么问题。 但是&#xff0c;如何避免进行修复工作呢&…

循环语句(2)

for的嵌套 //99乘法表for (int a 1; a < 9; a)-----控制行{for (int i 1; i < a; i)------控制列{Console.Write(i "*" a "" (a * i) "\t");}Console.WriteLine();}Console.ReadLine(); 结果 打印星号 //直角在左上for (int i …

通过Shell脚本将VSS项目批量创建并且提交迁移至Gitlab

脚本运行环境&#xff1a;Git Bash 系统环境&#xff1a;Windows 10 Pro 1709 VSS版本&#xff1a;Microsoft Visual SourceSafe 2005 我的VSS工作目录结构如下&#xff1a; D:\work\ --vss ----project1 ------src ------README.md ------ ...... ----project2 ------doc ----…

样式集(11)注册页面样式,全部代码附效果图

效果图&#xff1a; 代码&#xff1a; <template><view class"page"><view class"top">新用户注册</view><image :src"sanjiao" mode"widthFix" class"sanjiao"></image><!-- <…

quickselect_QuickSelect:使用代码示例解释的快速选择算法

quickselect什么是QuickSelect&#xff1f; (What is QuickSelect?) QuickSelect is a selection algorithm to find the K-th smallest element in an unsorted list.QuickSelect是一种选择算法&#xff0c;用于在未排序的列表中查找第K个最小的元素。 算法说明 (The Algori…

《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---34

以下为阅读《Linux命令行与shell脚本编程大全 第3版》的读书笔记&#xff0c;为了方便记录&#xff0c;特地与书的内容保持同步&#xff0c;特意做成一节一次随笔&#xff0c;特记录如下&#xff1a;转载于:https://www.cnblogs.com/guochaoxxl/p/7894620.html

CSS超出部分隐藏,显示滚动条

实现功能&#xff1a; 固定一个高度&#xff0c;超出该高度的部分就隐藏&#xff0c;并且显示滚动条能上拉下滑滚动 实现代码&#xff1a; height: 500rpx; overflow-x: hidden; overflow-y: scroll; 实现功能&#xff1a; 固定一个宽度&#xff0c;超出该宽度的部分就隐藏…

第二周学习进度

好久的编程实现&#xff0c;居然没有编完整&#xff0c;看来自己需要加班学习了&#xff01;第二周学习进度如下&#xff1a; 第二周所花时间&#xff08;包括上课&#xff09;共计21小时代码量&#xff08;行&#xff09;220博客量&#xff08;篇&#xff09;4了解到的知识 1.…

如何在C ++中从容器中删除元素

How to remove elements from container is a common C interview question, so you can earn some brownie points if you read this page carefully. 如何从容器中删除元素是C 常见的面试问题&#xff0c;因此&#xff0c;如果仔细阅读此页&#xff0c;可以赚取布朗尼积分。 …

【BZOJ4282】慎二的随机数列 乱搞

【BZOJ4282】慎二的随机数列 Description 间桐慎二是间桐家著名的废柴&#xff0c;有一天&#xff0c;他在学校随机了一组随机数列&#xff0c; 准备使用他那强大的人工智能求出其最长上升子序列&#xff0c;但是天有不测风云&#xff0c;人有旦夕祸福&#xff0c;柳洞一成路过…

git phpstorm 配置

http://jingyan.baidu.com/album/a948d65105faed0a2dcd2ea2.html?stepindex2&st2&os0&bd_page_type1&net_type3 http://jingyan.baidu.com/article/20095761cbef40cb0721b417.html转载于:https://www.cnblogs.com/fyy-888/p/5272862.html

CSS动画无限循环

实现代码 div{animation:myanimation 5s infinite; }keyframes myanimation {from {top:0px;}to {top:200px;} } 注:animation ->Css3动画属性 myanimation->随便命名 infinite 可重复 ,去掉就不重复了 top可以改为宽高,或者方向等等任何CSS属性 form 开始 to结束…

apple id无法创建_我如何为我的Apple收藏夹创建网站

apple id无法创建A while ago I started an Apple collection. Ive been following Apple hardware (and its aesthetics) since I was a teenager, but at that time I didnt the have money to own a Mac. 前一段时间&#xff0c;我开始了一个苹果系列。 从我十几岁起我就一直…

bzoj1562[NOI2009]变换序列——2016——3——12

任意门&#xff1a;http://www.lydsy.com/JudgeOnline/problem.php?id1562 题目&#xff1a; 对于0,1,…,N-1的N个整数&#xff0c;给定一个距离序列D0,D1,…,DN-1&#xff0c;定义一个变换序列T0,T1,…,TN-1使得每个i,Ti的环上距离等于Di。一个合法的变换序列应是0,1,…,N-1的…

把view或者div绘制 canvas ,导出图片功能实现完整源码附效果图(兼容H5和小程序)

先看下效果图&#xff1a;&#xff08;上面灰色块内的用div和CSS写出来的&#xff0c;然后绘制到canvas&#xff09; 实现此功能需要使用到一个微信小程序的插件&#xff0c;插件官方文档地址&#xff1a; wxml-to-canvas | 微信开放文档 本博客代码环境&#xff0c;uniapp&a…

C 语言中的 switch 语句 case 后面是否需要加大括号

事件原由为编辑器的自动缩进&#xff0c;当 case 换行后不自动缩进。 于是在在想可以可否在 case 后面再大括号&#xff0c;让其自动缩进。 查了资料&#xff0c;发现 case 是可以加大括号的&#xff0c;相当于代码块。 而且还有另外一个用途&#xff0c;可以代码块头部定义变量…

问题 c: 插入排序_插入排序:它是什么,以及它如何工作

问题 c: 插入排序Insertion sort is a simple sorting algorithm for a small number of elements.插入排序是一种针对少量元素的简单排序算法。 例&#xff1a; (Example:) In Insertion sort, you compare the key element with the previous elements. If the previous ele…