技术分享之IntelliJ plugin

news2024/11/27 6:26:30

资料

https://zhaojian.blog.csdn.net/article/details/127882946
Plugin Configuration File https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html

今天分享的主要内容:

了解插件能够做什么
如何开发一个插件
阅读两个常用的插件源码
intellij的窗口样式,及学习插件的方法
官方案例源码品读

从一个ScrcpyController插件开始

安卓控制软件scrcpy
终端输入命令 scrcpy -s 98KAY15DVD(设备号)
在这里插入图片描述
多个设备还得需要加上设备号,太繁琐.
有没有更好的方法,有,ScrcpyController, 一个IDE的插件
在这里插入图片描述
图1 ScrcpyController

把所有的功能,通过UI的方式显示出来,并且列出了所有的设备号.

Android Studio是Intellij+插件的形式

在Android Studio的软件目录, 找到plugin文件夹.
会发现有很多的android插件
在这里插入图片描述

创建一个plugin项目

新建New
在这里插入图片描述
创建的目录结构
在这里插入图片描述
配置run命令
在这里插入图片描述
正常的run和debug程序
在这里插入图片描述
像开发安卓程序一样打断点Debug就行.

plugin.xml中都有什么
从官网查询

Plugin Configuration File

https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html

ScrcpyController源码解析

目录结构
在这里插入图片描述
重要组成
在这里插入图片描述
创建要显示的界面
GUI Form, .form和java文件同时创建,在编辑的时候,也会生成句柄
在这里插入图片描述
此插件的界面显示有哪些:

刚开头的时候,说了他的主界面,还有settings中的配置文件.
settings文件
在这里插入图片描述
图2 ScrcpyControllerSettingsComponent
在这里插入图片描述
图3 TextDialog 通用弹窗
plugin.xml中配置
在这里插入图片描述
持久化数据

Persisting State of Components

https://plugins.jetbrains.com/docs/intellij/persisting-state-of-components.html

extend PersistentStateComponent

mark a service as implementing the PersistentStateComponent interface
define the state class
specify the storage location using @com.intellij.openapi.components.State

在这里插入图片描述

<idea-plugin>
	<extensions defaultExtensionNs="com.intellij">
	<applicationService serviceImplementation="com.codertainment.scrcpy.controller.model.ScrcpyProps"/>
	</extensions>
</idea-plugin>

在这里插入图片描述
此时,完整的界面就完成了.

执行命令
在这里插入图片描述

再看一个GsonFormatPlus插件
目录结构
在这里插入图片描述
plugin.xml文件

GenerateGroup是generate菜单栏的group-id

<actions>
    <action id="GsonFormatPlus" class="com.foxsteps.gsonformat.MainAction" text="GsonFormatPlus">
        <!--Generage弹出菜单-->
        <add-to-group group-id="GenerateGroup" anchor="last"/>
        <keyboard-shortcut keymap="$default" first-keystroke="alt s"/>
    </action>
</actions>

主界面
在这里插入图片描述
JsonDialog.java
JsonDialog.form

Setting界面
在这里插入图片描述
SettingDialog.java
SettingDialog.form

Model界面
在这里插入图片描述
FieldsDialog.java
FieldsDialog.form

{
“cat” : “feline”,
“dog” : “canine”,
“rat” : “murine”
}

生成代码
在这里插入图片描述

  • 通过PsiFile, PsiClass读取类信息 ConvertBridge#parseJson
  • ClassEntity编辑类 ConvertBridge#handleVirgoMode
  • DataWriter写入文件 FieldsDialog#run

如何依赖插件(主要解决依赖问题)

在这里插入图片描述
如何找到依赖插件ID

1.找到官网Dependencies文档(https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html#jetbrains-marketplace)有一些使用的插件

2.在插件市场,找到你想用的插件,在任意version中,点击展开, 左上角就有plugin id (https://plugins.jetbrains.com/plugin/8097-graphql)
在这里插入图片描述
在这里插入图片描述

IntelliJ都包括布局结构

官网文档 https://www.jetbrains.com/help/idea/getting-started.html

Tool Windows https://www.jetbrains.com/help/idea/tool-windows.html

几种常见的Tool Window
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
更多的官方案例-便于快速入手

git地址 git@github.com:AdrianAndroid/intellij-sdk-code-samples.git

在这里插入图片描述

<action id="org.intellij.sdk.action.PopupDialogAction" class="org.intellij.sdk.action.PopupDialogAction"
        text="Action Basics Plugin: Pop Dialog Action" description="SDK action example"
        icon="SdkIcons.Sdk_default_icon">
  <add-to-group group-id="ToolsMenu" anchor="first"/>
  <override-text place="MainMenu" text="Pop Dialog Action"/>
  <keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>
  <mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
</action>
public class PopupDialogAction extends AnAction {
    /**
     * Gives the user feedback when the dynamic action menu is chosen.
     * Pops a simple message dialog. See the psi_demo plugin for an
     * example of how to use {@link AnActionEvent} to access data.
     *
     * @param event Event received when the associated menu item is chosen.
     */
    
    public void actionPerformed( AnActionEvent event) {
        // Using the event, create and show a dialog
        Project currentProject = event.getProject();
        StringBuilder dlgMsg = new StringBuilder(event.getPresentation().getText() + " Selected!");
        String dlgTitle = event.getPresentation().getDescription();
        // If an element is selected in the editor, add info about it.
        Navigatable nav = event.getData(CommonDataKeys.NAVIGATABLE);
        if (nav != null) {
            dlgMsg.append(String.format("\nSelected Element: %s", nav.toString()));
        }
        Messages.showMessageDialog(currentProject, dlgMsg.toString(), dlgTitle, Messages.getInformationIcon());
    }

    /**
     * Determines whether this menu item is available for the current context.
     * Requires a project to be open.
     *
     * @param e Event received when the associated group-id menu is chosen.
     */
    
    public void update(AnActionEvent e) {
        // Set the availability based on whether a project is open
        Project project = e.getProject();
        e.getPresentation().setEnabledAndVisible(project != null);
    }
}

GroupedActions
在这里插入图片描述

<group id="org.intellij.sdk.action.GroupedActions"
text="Static Grouped Actions" description="SDK statically grouped action example"
popup="true" icon="SdkIcons.Sdk_default_icon">
<add-to-group group-id="ToolsMenu" anchor="after" relative-to-action="org.intellij.sdk.action.PopupDialogAction"/>
<action id="org.intellij.sdk.action.GroupPopDialogAction" class="org.intellij.sdk.action.PopupDialogAction"
text="A Group Action" description="SDK static grouped action example"
icon="SdkIcons.Sdk_default_icon">
</action>
</group>

DynamicActionGroup
在这里插入图片描述




relative-to-action相对于某一个选项的位置

通过代码动态添加
public class DynamicActionGroup extends ActionGroup {
@Override
public AnAction @NotNull [] getChildren(AnActionEvent e) {
return new AnAction[]{
new PopupDialogAction(“Action Added at Runtime”, “Dynamic Action Demo”, SdkIcons.Sdk_default_icon)
};
}
}

CustomDefaultActionGroup
在这里插入图片描述



group-id是EditorPopupMenu,右键弹出的菜单栏
public class CustomDefaultActionGroup extends DefaultActionGroup {
@Override
public void update(AnActionEvent event) {
// Enable/disable depending on whether user is editing
Editor editor = event.getData(CommonDataKeys.EDITOR);
event.getPresentation().setEnabled(editor != null); // 设置弹出的菜单是否可以点击
// Take this opportunity to set an icon for the group.
event.getPresentation().setIcon(SdkIcons.Sdk_default_icon);
}
}

在这里插入图片描述
在这里插入图片描述





@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
MyLog.log(this, “actionPerformed”);
// Get access to the editor and caret model. update() validated editor’s existence.
final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
final CaretModel caretModel = editor.getCaretModel();
// Getting the primary caret ensures we get the correct one of a possible many.
final Caret primaryCaret = caretModel.getPrimaryCaret();
// Get the caret information
LogicalPosition logicalPos = primaryCaret.getLogicalPosition();
VisualPosition visualPos = primaryCaret.getVisualPosition();
int caretOffset = primaryCaret.getOffset();
// Build and display the caret report.
String report = logicalPos.toString() + “\n” + visualPos.toString() + “\n” + "Offset: " + caretOffset;
Messages.showInfoMessage(report, “Caret Parameters Inside The Editor”);
}

*Editor Add Caret
在这里插入图片描述



@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
MyLog.log(this, “actionPerformed”);
// Editor is known to exist from update, so it’s not null
final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
// Get the action manager in order to get the necessary action handler…
final EditorActionManager actionManager = EditorActionManager.getInstance();
// Get the action handler registered to clone carets
final EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
// Clone one caret below the active caret
actionHandler.execute(editor, editor.getCaretModel().getPrimaryCaret(), e.getDataContext());
}

  • Editor Replace Text 替换原有的字符串

System.out.println(“sdfdfsdfsdfadsfsad”);

System.out.println(“editor_basics”);



@Override
public void actionPerformed(@NotNull final AnActionEvent e) {
MyLog.log(this, “actionPerformed”);
// Get all the required data from data keys
// Editor and Project were verified in update(), so they are not null.
final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
final Project project = e.getRequiredData(CommonDataKeys.PROJECT);
final Document document = editor.getDocument();
// Work off of the primary caret to get the selection info
Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
int start = primaryCaret.getSelectionStart();
int end = primaryCaret.getSelectionEnd();
// Replace the selection with a fixed string.
// Must do this document change in a write action context.
WriteCommandAction.runWriteCommandAction(project, () ->
document.replaceString(start, end, “editor_basics”)
);
// De-select the text range that was just replaced
primaryCaret.removeSelection();
}

*MyTypedHandler 监听打字输入到(0,0)的位置



class MyTypedHandler extends TypedHandlerDelegate {
@NotNull
@Override
public Result charTyped(char c, @NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
MyLog.log(this, "charTyped -> " + c);
// Get the document and project
final Document document = editor.getDocument();
// Construct the runnable to substitute the string at offset 0 in the document
Runnable runnable = () -> document.insertString(0, “editor_basics\n”);
// Make the document change in the context of a write action.
WriteCommandAction.runWriteCommandAction(project, runnable);
return Result.STOP;
}
}

最多能打开几个项目(max_opend_project)
在这里插入图片描述

全局监听的Listener

IDE层级的注册

应用服务


public class ProjectOpenCloseListener implements ProjectManagerListener {
@Override
public void projectOpened(@NotNull Project project) {
// Ensure this isn’t part of testing
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
// Get the counting service
ProjectCountingService projectCountingService = ApplicationManager.getApplication().getService(ProjectCountingService.class);
// Increment the project count
projectCountingService.incrProjectCount();
// See if the total # of projects violates the limit.
if (projectCountingService.projectLimitExceeded()) {
// Transitioned to outside the limit
String title = String.format(“Opening Project “%s””, project.getName());
String message = “
The number of open projects exceeds the SDK plugin max_opened_projects limit.

” +
“This is not an error

”;
Messages.showMessageDialog(project, message, title, Messages.getInformationIcon());
}
}
@Override
public void projectClosed(@NotNull Project project) {
// Ensure this isn’t part of testing
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
// Get the counting service
ProjectCountingService projectCountingService =
ApplicationManager.getApplication().getService(ProjectCountingService.class);
// Decrement the count because a project just closed
projectCountingService.decrProjectCount();
}
}
获取项目环境信息(project_model)

Project https://plugins.jetbrains.com/docs/intellij/project.html

SDK https://plugins.jetbrains.com/docs/intellij/sdk.html

Library https://plugins.jetbrains.com/docs/intellij/library.html

Show Source Roots



在这里插入图片描述
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project == null) {
return;
}
String projectName = project.getName();
StringBuilder sourceRootsList = new StringBuilder();
VirtualFile[] vFiles = ProjectRootManager.getInstance(project).getContentSourceRoots();
for (VirtualFile file : vFiles) {
sourceRootsList.append(file.getUrl()).append(“\n”);
}
Messages.showInfoMessage(
“Source roots for the " + projectName + " plugin:\n” + sourceRootsList.toString(),
“Project Properties”
);
}

在这里插入图片描述
Show Sdk Info




@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project != null) {
Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
if (sdk != null) {
String projectSDKName = sdk.getName();
String newProjectSdkName = “New Sdk Name”;
ProjectRootManager.getInstance(project).setProjectSdkName(newProjectSdkName, sdk.getSdkType().getName());
Messages.showInfoMessage(projectSDKName + " has changed to " + newProjectSdkName, “Project Sdk Info”);
}
}
}

在这里插入图片描述
FileProjectIndex in Action

在这里插入图片描述



@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
final Editor editor = event.getData(CommonDataKeys.EDITOR);
if (project == null || editor == null) {
return;
}
Document document = editor.getDocument();
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
VirtualFile virtualFile = fileDocumentManager.getFile(document);
ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
if (virtualFile != null) {
Module module = projectFileIndex.getModuleForFile(virtualFile);
String moduleName;
moduleName = module != null ? module.getName() : “No module defined for file”;

VirtualFile moduleContentRoot = projectFileIndex.getContentRootForFile(virtualFile);
boolean isLibraryFile = projectFileIndex.isLibraryClassFile(virtualFile);
boolean isInLibraryClasses = projectFileIndex.isInLibraryClasses(virtualFile);
boolean isInLibrarySource = projectFileIndex.isInLibrarySource(virtualFile);
Messages.showInfoMessage("Module: " + moduleName + "\n" +
                "Module content root: " + moduleContentRoot + "\n" +
                "Is library file: " + isLibraryFile + "\n" +
                "Is in library classes: " + isInLibraryClasses +
                ", Is in library source: " + isInLibrarySource,
        "Main File Info for" + virtualFile.getName());

}

Project Modification in Action

Actions https://plugins.jetbrains.com/docs/intellij/basic-action-system.html

CommonDataKeys https://dploeger.github.io/intellij-api-doc/com/intellij/openapi/actionSystem/CommonDataKeys.html#HOST_EDITOR



@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project == null) {
return;
}
Navigatable element = event.getData(CommonDataKeys.NAVIGATABLE);
if (element instanceof PsiClass) {
PsiFile file = ((PsiClass) element).getContainingFile();
if (file == null) {
return;
}
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
return;
}
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final Module module = fileIndex.getModuleForFile(virtualFile);
if (module == null) {
return;
}
if (!ModuleRootManager.getInstance(module).getFileIndex().isInContent(virtualFile)) {
ModuleRootModificationUtil.addModuleLibrary(module, virtualFile.getUrl());
}
}
}

Libraries for File
在这里插入图片描述
类文件的信息(psi_demo)
PSI

Navigating the PSI https://plugins.jetbrains.com/docs/intellij/navigating-psi.html

Program Structure Interface (PSI) https://plugins.jetbrains.com/docs/intellij/psi.html

PSI Files https://plugins.jetbrains.com/docs/intellij/psi-files.html

在这里插入图片描述

Unlike VirtualFile and Document, which have application scope (even if multiple projects are open, each file is represented by the same VirtualFile instance),

PSI has project scope: the same file is represented by multiple PsiFile instances if the file belongs to multiple projects open at the same time.

在这里插入图片描述
拓展: Document

Documents https://plugins.jetbrains.com/docs/intellij/documents.html

A Document is an editable sequence of Unicode characters, typically corresponding to the text contents of a virtual file.

拓展:Virutal File

Virtual File System https://plugins.jetbrains.com/docs/intellij/virtual-file-system.html

Virtual Files https://plugins.jetbrains.com/docs/intellij/virtual-file.html

A VirtualFile (VF) is the IntelliJ Platform’s representation of a file in a Virtual File System (VFS).

设置页面配置(settings)
在这里插入图片描述

public class AppSettingsConfigurable implements Configurable {

private AppSettingsComponent mySettingsComponent;

// A default constructor with no arguments is required because this implementation
// is registered as an applicationConfigurable EP

@Nls(capitalization = Nls.Capitalization.Title)
@Override
public String getDisplayName() {
    return "SDK: Application Settings Example";
}

@Override
public JComponent getPreferredFocusedComponent() {
    return mySettingsComponent.getPreferredFocusedComponent();
}

@Nullable
@Override
public JComponent createComponent() {
    mySettingsComponent = new AppSettingsComponent();
    return mySettingsComponent.getPanel();
}

@Override
public boolean isModified() {
    AppSettingsState settings = AppSettingsState.getInstance();
    boolean modified = !mySettingsComponent.getUserNameText().equals(settings.userId);
    modified |= mySettingsComponent.getIdeaUserStatus() != settings.ideaStatus;
    return modified;
}

@Override
public void apply() {
    AppSettingsState settings = AppSettingsState.getInstance();
    settings.userId = mySettingsComponent.getUserNameText();
    settings.ideaStatus = mySettingsComponent.getIdeaUserStatus();
}

@Override
public void reset() {
    AppSettingsState settings = AppSettingsState.getInstance();
    mySettingsComponent.setUserNameText(settings.userId);
    mySettingsComponent.setIdeaUserStatus(settings.ideaStatus);
}

@Override
public void disposeUIResources() {
    mySettingsComponent = null;
}

}

public class AppSettingsComponent {

private final JPanel myMainPanel;
private final JBTextField myUserNameText = new JBTextField();
private final JBCheckBox myIdeaUserStatus = new JBCheckBox("Do you use IntelliJ IDEA? ");

public AppSettingsComponent() {
    myMainPanel = FormBuilder.createFormBuilder()
            .addLabeledComponent(new JBLabel("Enter user name: "), myUserNameText, 1, false)
            .addComponent(myIdeaUserStatus, 1)
            .addComponentFillVertically(new JPanel(), 0)
            .getPanel();
}

public JPanel getPanel() {
    return myMainPanel;
}

public JComponent getPreferredFocusedComponent() {
    return myUserNameText;
}

@NotNull
public String getUserNameText() {
    return myUserNameText.getText();
}

public void setUserNameText(@NotNull String newText) {
    myUserNameText.setText(newText);
}

public boolean getIdeaUserStatus() {
    return myIdeaUserStatus.isSelected();
}

public void setIdeaUserStatus(boolean newStatus) {
    myIdeaUserStatus.setSelected(newStatus);
}

}

@State(
name = “org.intellij.sdk.settings.AppSettingsState”,
storages = @Storage(“SdkSettingsPlugin.xml”)
)
public class AppSettingsState implements PersistentStateComponent {

public String userId = "John Q. Public";
public boolean ideaStatus = false;

public static AppSettingsState getInstance() {
    return ApplicationManager.getApplication().getService(AppSettingsState.class);
}

@Nullable
@Override
public AppSettingsState getState() {
    return this;
}

@Override
public void loadState(@NotNull AppSettingsState state) {
    XmlSerializerUtil.copyBean(state, this);
}

}

工具窗口ToolWindow

public class MyToolWindowFactory implements ToolWindowFactory {

/**
 * Create the tool window content.
 *
 * @param project    current project
 * @param toolWindow current tool window
 */
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
    MyToolWindow myToolWindow = new MyToolWindow(toolWindow);
    ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
    Content content = contentFactory.createContent(myToolWindow.getContent(), "", false);
    toolWindow.getContentManager().addContent(content);
}

}

public class MyToolWindow {
private JButton refreshToolWindowButton;
private JButton hideToolWindowButton;
private JLabel currentDate;
private JLabel currentTime;
private JLabel timeZone;
private JPanel myToolWindowContent;

public MyToolWindow(ToolWindow toolWindow) {
    hideToolWindowButton.addActionListener(e -> toolWindow.hide(null));
    refreshToolWindowButton.addActionListener(e -> currentDateTime());
    this.currentDateTime();
}

public void currentDateTime() {
    // Get current date and time
    Calendar instance = Calendar.getInstance();
    currentDate.setText(instance.get(Calendar.DAY_OF_MONTH) + "/" + (instance.get(Calendar.MONTH) + 1) + "/" + instance.get(Calendar.YEAR)
    );
    currentDate.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Calendar-icon.png")));
    int min = instance.get(Calendar.MINUTE);
    String strMin = min < 10 ? "0" + min : String.valueOf(min);
    currentTime.setText(instance.get(Calendar.HOUR_OF_DAY) + ":" + strMin);
    currentTime.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Time-icon.png")));
    // Get time zone
    long gmt_Offset = instance.get(Calendar.ZONE_OFFSET); // offset from GMT in milliseconds
    String str_gmt_Offset = String.valueOf(gmt_Offset / 3600000);
    str_gmt_Offset = (gmt_Offset > 0) ? "GMT + " + str_gmt_Offset : "GMT - " + str_gmt_Offset;
    timeZone.setText(str_gmt_Offset);
    timeZone.setIcon(new ImageIcon(getClass().getResource("/toolWindow/Time-zone-icon.png")));
}

public JPanel getContent() {
    return myToolWindowContent;
}

}

开发Intellij 插件,还能干什么
学习Android编译框架的原理
开发过程中的便捷工具

热门Android Studio 插件,这里是Top 20! https://juejin.cn/post/6854573213104472071

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/92213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

15.Django大型电商项目之创建模型与sql表反向生成模型

1.用户模块模型类创建 1.1 创建用户的子应用 python .\manage.py startapp userapp在settings中挂载子应用 创建子应用urls.py 在主应用中加入子应用的urls.py 1.2 创建表 如何在直接导入sql文件形成表&#xff0c;这里就直接在navicate中把sql文件拖进去点击开始即可 这里…

大数据技术系列:图解大数据平台开发

导言 在前面的文章《「大数据技术体系」学习实践导览》中&#xff0c;概要式的梳理了大数据平台的业务目标&#xff0c;大数据平台的架构框架&#xff0c;大数据平台中常用的技术及工具&#xff0c;数据治理四方面的内容&#xff0c;算是对自身所了解大数据知识体系的抛砖引玉…

第十四届蓝桥杯集训——JavaC组第十二篇——while循环(循环四要素)

第十四届蓝桥杯集训——JavaC组第十二篇——while循环(循环四要素) 前言 百度解析&#xff1a;以环形、回路或轨道运行;沿曲折的路线运行;特指运行一周而回到原处,再转。或说反复地连续做某事。 那么&#xff0c;在程序中依然是连续重复的按照一定的规则去执行某事。 程序计数器…

如何把视频分屏?教你轻松学会视频分屏

分屏视频该怎么操作&#xff1f;不知道大家有没有看到过这样一个视频&#xff0c;就是一个视频里有两个或者有更多个画面&#xff0c;我们在观看的时候可以同时看好几个画面。其实这就是分屏视频&#xff0c;在一个页面中加入多个画面。这样的视频是不是既好玩又炫酷呢&#xf…

尚硅谷Promise笔记

文章目录一、Promise介绍与基本使用1-1.初体验之promise封装ajax请求1-2.Promise对象状态属性PromiseState的值有三个1-3.Promise对象状态属性PromiseResults二、Promise API2-1.Promise构造函数Promise(excutor){}2-2.Promise.prototype.then 方式&#xff1a;(onResolved,onR…

App 黑白化技术实践

前言 很高兴遇见你~ 最近打开各大 App 会发现它们都做了黑白化&#xff0c;如下支付宝的处理&#xff1a; 可以看到应用设置了全局灰色调&#xff0c;表达了一种对逝者的哀悼&#xff0c;非常的应景和人性化。作为程序猿&#xff0c;我们来探索一下它从技术角度是怎么实现的。…

[附源码]Python计算机毕业设计SSM基于java旅游信息分享网站(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

汇编语言第2章—寄存器

8086CPU有14个寄存器&#xff0c;分别是&#xff1a;AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。2.1 通用寄存器 8086CPU的所有寄存器都是16位的&#xff0c;可以存放两个字节。AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据&#xff0c;称为通用…

【Spring】AOP记录日志

我的aop记录日志&#xff0c;可以记录&#xff1a;【 操作类型、操作描述、参数、登录项目的用户ip】 当然记录什么靠你自己决定。 一.自定义一个注解 Target({ElementType.METHOD,ElementType.PARAMETER}) Retention(RetentionPolicy.RUNTIME) Documented public interface A…

两位前阿里 P10 的成长经历的启发

目录 汤峥嵘的成长经历 关键节点一&#xff1a;到美国留学 关键节点二&#xff1a;美国工作十年 关键节点三&#xff1a;八年阿里时光 关键节点四&#xff1a;加入途牛和 VIPABC 毕玄的成长经历 关键节点一&#xff1a;小公司里脱颖而出 关键节点二&#xff1a;加入淘宝…

FineReport数据分析教程- 图表刷新接口

1. 概述 1.1 预期效果 点击按钮可以刷新普通报表或决策报表中的图表&#xff0c;以普通报表为例&#xff0c;效果如下图所示&#xff1a; 1.2 实现思路 通过FR.Chart.WebUtils.getChart("chartID").dataRefresh()获取要刷新的图表对象&#xff0c;其中chartID为图表…

程序员如何写一份更好的简历

简历中的常见错误 1. 信息过多&#xff0c;缺乏重点 信息过多的常见表现是十几行的技能列表&#xff0c; 我举一个血淋淋的例子&#xff1a; 20 行的技能列表&#xff0c;这位求职者开始就把自己了解的所有工具都列出来&#xff0c;希望能够突显自己的经验和学习能力&#xf…

pytorch基础操作(五)多层感知机的实现

1、多层感知机 1、激活函数的引入 这个多层感知机有4个输⼊&#xff0c;3个输出&#xff0c;其隐藏层包含5个隐藏单元。输⼊层不涉及任何计算&#xff0c;因此使⽤此⽹络产⽣输出只需要实现隐藏层和输出层的计算。因此&#xff0c;这个多层感知机中的层数为2。注意&#xff0…

小米盒子为什么搜不到电视家?电视安装包解析错误解决方案

不少的朋友在小米电视盒子上安装了美家市场软件商店后&#xff0c;却发现在市场里面没法安装想要的电视盒子直播软件&#xff0c;这是怎么回事呢&#xff1f;其实大部分原因是电视盒子机制的问题限制了安装&#xff0c;导致部分品牌电视盒子装软件时会弹出“无法安装”的提示。…

Mysql双主整理

目录 1. Mysql binlog参数配置 2. Mysql binlog查看详细内容 3. Mysql双主搭建 4. Mysql双主解决数据回环 4.1 双主同步测试一 4.1.1 测试总结 4.2 双主同步测试二 4.2.1 测试总结 4.3 双主同步测试三 4.3.1 测试总结 1. Mysql binlog参数配置 log-binmysql-bin 打…

水果FLStudio21.0.0软件最新版有哪些新增功能变化?

FL Studio(水果软件)21 引入更快、更精确的音频编辑、改进的内容发现、对 DAW 情绪的控制以及更多鼓舞人心的创意工具。FL Studio是一款功能非常强大的音乐创作编辑软件它就是FL Studio(水果软件)。使用FL Studio中文版可以轻松帮我们制作自己的音乐唱片&#xff0c;拥有强大且…

【ROS】HelloWord简单实现

C实现 1. 创建工作空间并初始化 创建工作目录demo01_ws&#xff0c;并在该文件夹下创建src文件夹 mkdir -p demo01_ws/src进入到该目录下 cd demo01_ws/初始化 catkin_make这时在demo01_ws目录下除了src文件夹外&#xff0c;多处了两个文件夹。 ![在这里插入图片描述](htt…

数字化门店转型| 水疗会所管理系统| 小程序搭建

水疗会所与沐足采耳、洗浴按摩等都属于休息享受型服务&#xff0c;是不少中年人的选择&#xff0c;一天的压力可以得到缓解&#xff0c;同时客单价一般在几百元左右&#xff0c;在水疗会所里可以洗澡蒸桑拿、桌游、乒乓球等&#xff0c;同时随着近些年来生活压力逐渐加大&#…

【C语言学习】详解二级指针

在学习数据结构时&#xff0c;通常会遇到调用函数无法对主函数中的全局变量进行有效的更改操作&#xff0c;这时我们就需要指针&#xff0c;但二级指针对于初学者而言有着一定的学习难度&#xff0c;本文通过代码结合实验调试来详细说明二级指针。 如果一个指针指向另一个指针&…

[附源码]Node.js计算机毕业设计高校图书服务系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…